diff --git a/.gitignore b/.gitignore index c1e83b8272..ee039fcb85 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ share/python-wheels/ .installed.cfg *.egg MANIFEST +node_modules # PyInstaller # Usually these files are written by a python script from a template diff --git a/alembic/versions/c0c4aaf84861_add_delete_cascade_variant_studies.py b/alembic/versions/c0c4aaf84861_add_delete_cascade_variant_studies.py new file mode 100644 index 0000000000..cc1100eeba --- /dev/null +++ b/alembic/versions/c0c4aaf84861_add_delete_cascade_variant_studies.py @@ -0,0 +1,51 @@ +""" +Add delete cascade constraint to variant study foreign keys + +Revision ID: c0c4aaf84861 +Revises: fd73601a9075 +Create Date: 2024-02-21 17:29:48.736664 +""" +from alembic import op # type: ignore + +# revision identifiers, used by Alembic. +revision = "c0c4aaf84861" +down_revision = "fd73601a9075" +branch_labels = None +depends_on = None + +COMMAND_BLOCK_FK = "commandblock_study_id_fkey" +SNAPSHOT_FK = "variant_study_snapshot_id_fkey" + + +def upgrade() -> None: + dialect_name: str = op.get_context().dialect.name + + # SQLite doesn't support dropping foreign keys, so we need to ignore it here + if dialect_name == "postgresql": + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table("commandblock", schema=None) as batch_op: + batch_op.drop_constraint(COMMAND_BLOCK_FK, type_="foreignkey") + batch_op.create_foreign_key(COMMAND_BLOCK_FK, "variantstudy", ["study_id"], ["id"], ondelete="CASCADE") + + with op.batch_alter_table("variant_study_snapshot", schema=None) as batch_op: + batch_op.drop_constraint(SNAPSHOT_FK, type_="foreignkey") + batch_op.create_foreign_key(SNAPSHOT_FK, "variantstudy", ["id"], ["id"], ondelete="CASCADE") + + # ### end Alembic commands ### + + +def downgrade() -> None: + dialect_name: str = op.get_context().dialect.name + + # SQLite doesn't support dropping foreign keys, so we need to ignore it here + if dialect_name == "postgresql": + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table("variant_study_snapshot", schema=None) as batch_op: + batch_op.drop_constraint(SNAPSHOT_FK, type_="foreignkey") + batch_op.create_foreign_key(SNAPSHOT_FK, "variantstudy", ["id"], ["id"]) + + with op.batch_alter_table("commandblock", schema=None) as batch_op: + batch_op.drop_constraint(COMMAND_BLOCK_FK, type_="foreignkey") + batch_op.create_foreign_key(COMMAND_BLOCK_FK, "variantstudy", ["study_id"], ["id"]) + + # ### end Alembic commands ### diff --git a/alembic/versions/dae93f1d9110_populate_tag_and_study_tag_tables_with_.py b/alembic/versions/dae93f1d9110_populate_tag_and_study_tag_tables_with_.py new file mode 100644 index 0000000000..6fbb060115 --- /dev/null +++ b/alembic/versions/dae93f1d9110_populate_tag_and_study_tag_tables_with_.py @@ -0,0 +1,123 @@ +""" +Populate `tag` and `study_tag` tables from `patch` field in `study_additional_data` table + +Revision ID: dae93f1d9110 +Revises: 3c70366b10ea +Create Date: 2024-02-08 10:30:20.590919 +""" +import collections +import itertools +import json +import secrets +import typing as t + +import sqlalchemy as sa # type: ignore +from alembic import op +from sqlalchemy.engine import Connection # type: ignore + +from antarest.study.css4_colors import COLOR_NAMES + +# revision identifiers, used by Alembic. +revision = "dae93f1d9110" +down_revision = "3c70366b10ea" +branch_labels = None +depends_on = None + + +def _avoid_duplicates(tags: t.Iterable[str]) -> t.Sequence[str]: + """Avoid duplicate tags (case insensitive)""" + + upper_tags = {tag.upper(): tag for tag in tags} + return list(upper_tags.values()) + + +def _load_patch_obj(patch: t.Optional[str]) -> t.MutableMapping[str, t.Any]: + """Load the patch object from the `patch` field in the `study_additional_data` table.""" + + obj: t.MutableMapping[str, t.Any] = json.loads(patch or "{}") + obj["study"] = obj.get("study") or {} + obj["study"]["tags"] = _avoid_duplicates(obj["study"].get("tags") or []) + return obj + + +def upgrade() -> None: + """ + Populate `tag` and `study_tag` tables from `patch` field in `study_additional_data` table + + Four steps to proceed: + - Retrieve study-tags pairs from patches in `study_additional_data`. + - Delete all rows in `tag` and `study_tag`, as tag updates between revised 3c70366b10ea and this version, + do modify the data in patches alongside the two previous tables. + - Populate `tag` table using unique tag-labels and by randomly generating their associated colors. + - Populate `study_tag` using study-tags pairs. + """ + + # create connexion to the db + connexion: Connection = op.get_bind() + + # retrieve the tags and the study-tag pairs from the db + study_tags = connexion.execute("SELECT study_id, patch FROM study_additional_data") + tags_by_ids: t.MutableMapping[str, t.Set[str]] = {} + for study_id, patch in study_tags: + obj = _load_patch_obj(patch) + tags_by_ids[study_id] = obj["study"]["tags"] + + # delete rows in tables `tag` and `study_tag` + connexion.execute("DELETE FROM study_tag") + connexion.execute("DELETE FROM tag") + + # insert the tags in the `tag` table + all_labels = {lbl.upper(): lbl for lbl in itertools.chain.from_iterable(tags_by_ids.values())} + bulk_tags = [{"label": label, "color": secrets.choice(COLOR_NAMES)} for label in all_labels.values()] + if bulk_tags: + sql = sa.text("INSERT INTO tag (label, color) VALUES (:label, :color)") + connexion.execute(sql, *bulk_tags) + + # Create relationships between studies and tags in the `study_tag` table + bulk_study_tags = [ + # fmt: off + {"study_id": id_, "tag_label": all_labels[lbl.upper()]} + for id_, tags in tags_by_ids.items() + for lbl in tags + # fmt: on + ] + if bulk_study_tags: + sql = sa.text("INSERT INTO study_tag (study_id, tag_label) VALUES (:study_id, :tag_label)") + connexion.execute(sql, *bulk_study_tags) + + +def downgrade() -> None: + """ + Restore `patch` field in `study_additional_data` from `tag` and `study_tag` tables + + Three steps to proceed: + - Retrieve study-tags pairs from `study_tag` table. + - Update patches study-tags in `study_additional_data` using these pairs. + - Delete all rows from `tag` and `study_tag`. + """ + # create a connection to the db + connexion: Connection = op.get_bind() + + # Creating the `tags_by_ids` mapping from data in the `study_tags` table + tags_by_ids: t.MutableMapping[str, t.Set[str]] = collections.defaultdict(set) + study_tags = connexion.execute("SELECT study_id, tag_label FROM study_tag") + for study_id, tag_label in study_tags: + tags_by_ids[study_id].add(tag_label) + + # Then, we read objects from the `patch` field of the `study_additional_data` table + objects_by_ids = {} + study_tags = connexion.execute("SELECT study_id, patch FROM study_additional_data") + for study_id, patch in study_tags: + obj = _load_patch_obj(patch) + obj["study"]["tags"] = _avoid_duplicates(tags_by_ids[study_id] | set(obj["study"]["tags"])) + objects_by_ids[study_id] = obj + + # Updating objects in the `study_additional_data` table + bulk_patches = [{"study_id": id_, "patch": json.dumps(obj)} for id_, obj in objects_by_ids.items()] + if bulk_patches: + sql = sa.text("UPDATE study_additional_data SET patch = :patch WHERE study_id = :study_id") + connexion.execute(sql, *bulk_patches) + + # Deleting study_tags and tags + connexion.execute("DELETE FROM study_tag") + connexion.execute("DELETE FROM tag") diff --git a/alembic/versions/fd73601a9075_add_delete_cascade_studies.py b/alembic/versions/fd73601a9075_add_delete_cascade_studies.py new file mode 100644 index 0000000000..3f9f42c684 --- /dev/null +++ b/alembic/versions/fd73601a9075_add_delete_cascade_studies.py @@ -0,0 +1,86 @@ +""" +Add delete cascade constraint to study foreign keys + +Revision ID: fd73601a9075 +Revises: 3c70366b10ea +Create Date: 2024-02-12 17:27:37.314443 +""" +import sqlalchemy as sa # type: ignore +from alembic import op + +# revision identifiers, used by Alembic. +revision = "fd73601a9075" +down_revision = "dae93f1d9110" +branch_labels = None +depends_on = None + +# noinspection SpellCheckingInspection +RAWSTUDY_FK = "rawstudy_id_fkey" + +# noinspection SpellCheckingInspection +VARIANTSTUDY_FK = "variantstudy_id_fkey" + +# noinspection SpellCheckingInspection +STUDY_ADDITIONAL_DATA_FK = "study_additional_data_study_id_fkey" + + +def upgrade() -> None: + dialect_name: str = op.get_context().dialect.name + + # SQLite doesn't support dropping foreign keys, so we need to ignore it here + if dialect_name == "postgresql": + with op.batch_alter_table("rawstudy", schema=None) as batch_op: + batch_op.drop_constraint(RAWSTUDY_FK, type_="foreignkey") + batch_op.create_foreign_key(RAWSTUDY_FK, "study", ["id"], ["id"], ondelete="CASCADE") + + with op.batch_alter_table("study_additional_data", schema=None) as batch_op: + batch_op.drop_constraint(STUDY_ADDITIONAL_DATA_FK, type_="foreignkey") + batch_op.create_foreign_key(STUDY_ADDITIONAL_DATA_FK, "study", ["study_id"], ["id"], ondelete="CASCADE") + + with op.batch_alter_table("variantstudy", schema=None) as batch_op: + batch_op.drop_constraint(VARIANTSTUDY_FK, type_="foreignkey") + batch_op.create_foreign_key(VARIANTSTUDY_FK, "study", ["id"], ["id"], ondelete="CASCADE") + + with op.batch_alter_table("group_metadata", schema=None) as batch_op: + batch_op.alter_column("group_id", existing_type=sa.VARCHAR(length=36), nullable=False) + batch_op.alter_column("study_id", existing_type=sa.VARCHAR(length=36), nullable=False) + batch_op.create_index(batch_op.f("ix_group_metadata_group_id"), ["group_id"], unique=False) + batch_op.create_index(batch_op.f("ix_group_metadata_study_id"), ["study_id"], unique=False) + if dialect_name == "postgresql": + batch_op.drop_constraint("group_metadata_group_id_fkey", type_="foreignkey") + batch_op.drop_constraint("group_metadata_study_id_fkey", type_="foreignkey") + batch_op.create_foreign_key( + "group_metadata_group_id_fkey", "groups", ["group_id"], ["id"], ondelete="CASCADE" + ) + batch_op.create_foreign_key( + "group_metadata_study_id_fkey", "study", ["study_id"], ["id"], ondelete="CASCADE" + ) + + +def downgrade() -> None: + dialect_name: str = op.get_context().dialect.name + # SQLite doesn't support dropping foreign keys, so we need to ignore it here + if dialect_name == "postgresql": + with op.batch_alter_table("rawstudy", schema=None) as batch_op: + batch_op.drop_constraint(RAWSTUDY_FK, type_="foreignkey") + batch_op.create_foreign_key(RAWSTUDY_FK, "study", ["id"], ["id"]) + + with op.batch_alter_table("study_additional_data", schema=None) as batch_op: + batch_op.drop_constraint(STUDY_ADDITIONAL_DATA_FK, type_="foreignkey") + batch_op.create_foreign_key(STUDY_ADDITIONAL_DATA_FK, "study", ["study_id"], ["id"]) + + with op.batch_alter_table("variantstudy", schema=None) as batch_op: + batch_op.drop_constraint(VARIANTSTUDY_FK, type_="foreignkey") + batch_op.create_foreign_key(VARIANTSTUDY_FK, "study", ["id"], ["id"]) + + with op.batch_alter_table("group_metadata", schema=None) as batch_op: + # SQLite doesn't support dropping foreign keys, so we need to ignore it here + if dialect_name == "postgresql": + batch_op.drop_constraint("group_metadata_study_id_fkey", type_="foreignkey") + batch_op.drop_constraint("group_metadata_group_id_fkey", type_="foreignkey") + batch_op.create_foreign_key("group_metadata_study_id_fkey", "study", ["study_id"], ["id"]) + batch_op.create_foreign_key("group_metadata_group_id_fkey", "groups", ["group_id"], ["id"]) + batch_op.drop_index(batch_op.f("ix_group_metadata_study_id")) + batch_op.drop_index(batch_op.f("ix_group_metadata_group_id")) + batch_op.alter_column("study_id", existing_type=sa.VARCHAR(length=36), nullable=True) + batch_op.alter_column("group_id", existing_type=sa.VARCHAR(length=36), nullable=True) diff --git a/antarest/__init__.py b/antarest/__init__.py index f4fae4cd35..9895b016bd 100644 --- a/antarest/__init__.py +++ b/antarest/__init__.py @@ -7,9 +7,9 @@ # Standard project metadata -__version__ = "2.16.8" +__version__ = "2.17" __author__ = "RTE, Antares Web Team" -__date__ = "2024-04-19" +__date__ = "2024-05-15" # noinspection SpellCheckingInspection __credits__ = "(c) Réseau de Transport de l’Électricité (RTE)" diff --git a/antarest/core/configdata/model.py b/antarest/core/configdata/model.py index 8db2522b43..cb58784493 100644 --- a/antarest/core/configdata/model.py +++ b/antarest/core/configdata/model.py @@ -2,8 +2,7 @@ from typing import Any, Optional from pydantic import BaseModel -from sqlalchemy import Boolean, Column, DateTime, ForeignKey, Integer, Sequence, String # type: ignore -from sqlalchemy.orm import relationship # type: ignore +from sqlalchemy import Column, Integer, String # type: ignore from antarest.core.persistence import Base diff --git a/antarest/core/exceptions.py b/antarest/core/exceptions.py index 1755d001df..0ca8af4f7d 100644 --- a/antarest/core/exceptions.py +++ b/antarest/core/exceptions.py @@ -1,5 +1,6 @@ +import re +import typing as t from http import HTTPStatus -from typing import Optional from fastapi.exceptions import HTTPException @@ -8,44 +9,149 @@ class ShouldNotHappenException(Exception): pass -class STStorageFieldsNotFoundError(HTTPException): - """Fields of the short-term storage are not found""" +# ============================================================ +# Exceptions related to the study configuration (`.ini` files) +# ============================================================ - def __init__(self, storage_id: str) -> None: - detail = f"Fields of storage '{storage_id}' not found" - super().__init__(HTTPStatus.NOT_FOUND, detail) +# Naming convention for exceptions related to the study configuration: +# +# | Topic | NotFound (404) | Duplicate (409) | Invalid (422) | +# |---------------|-----------------------|------------------------|----------------------| +# | ConfigFile | ConfigFileNotFound | N/A | InvalidConfigFile | +# | ConfigSection | ConfigSectionNotFound | DuplicateConfigSection | InvalidConfigSection | +# | ConfigOption | ConfigOptionNotFound | DuplicateConfigOption | InvalidConfigOption | +# | Matrix | MatrixNotFound | DuplicateMatrix | InvalidMatrix | - def __str__(self) -> str: - return self.detail +THERMAL_CLUSTER = "thermal cluster" +RENEWABLE_CLUSTER = "renewable cluster" +SHORT_TERM_STORAGE = "short-term storage" + +# ============================================================ +# NotFound (404) +# ============================================================ + +_match_input_path = re.compile(r"input(?:/[\w*-]+)+").fullmatch + + +class ConfigFileNotFound(HTTPException): + """ + Exception raised when a configuration file is not found (404 Not Found). + + Notes: + The study ID is not provided because it is implicit. -class STStorageMatrixNotFoundError(HTTPException): - """Matrix of the short-term storage is not found""" + Attributes: + path: Path of the missing file(s) relative to the study directory. + area_ids: Sequence of area IDs for which the file(s) is/are missing. + """ - def __init__(self, study_id: str, area_id: str, storage_id: str, ts_name: str) -> None: - detail = f"Time series '{ts_name}' of storage '{storage_id}' not found" + object_name = "" + """Name of the object that is not found: thermal, renewables, etc.""" + + def __init__(self, path: str, *area_ids: str): + assert _match_input_path(path), f"Invalid path: '{path}'" + self.path = path + self.area_ids = area_ids + ids = ", ".join(f"'{a}'" for a in area_ids) + detail = { + 0: f"Path '{path}' not found", + 1: f"Path '{path}' not found for area {ids}", + 2: f"Path '{path}' not found for areas {ids}", + }[min(len(area_ids), 2)] + if self.object_name: + detail = f"{self.object_name.title()} {detail}" super().__init__(HTTPStatus.NOT_FOUND, detail) def __str__(self) -> str: + """Return a string representation of the exception.""" return self.detail -class STStorageConfigNotFoundError(HTTPException): - """Configuration for short-term storage is not found""" +class ThermalClusterConfigNotFound(ConfigFileNotFound): + """Configuration for thermal cluster is not found (404 Not Found)""" + + object_name = THERMAL_CLUSTER + + +class RenewableClusterConfigNotFound(ConfigFileNotFound): + """Configuration for renewable cluster is not found (404 Not Found)""" + + object_name = RENEWABLE_CLUSTER + + +class STStorageConfigNotFound(ConfigFileNotFound): + """Configuration for short-term storage is not found (404 Not Found)""" - def __init__(self, study_id: str, area_id: str) -> None: - detail = f"The short-term storage configuration of area '{area_id}' not found" + object_name = SHORT_TERM_STORAGE + + +class ConfigSectionNotFound(HTTPException): + """ + Exception raised when a configuration section is not found (404 Not Found). + + Notes: + The study ID is not provided because it is implicit. + + Attributes: + path: Path of the missing file(s) relative to the study directory. + section_id: ID of the missing section. + """ + + object_name = "" + """Name of the object that is not found: thermal, renewables, etc.""" + + def __init__(self, path: str, section_id: str): + assert _match_input_path(path), f"Invalid path: '{path}'" + self.path = path + self.section_id = section_id + object_name = self.object_name or "section" + detail = f"{object_name.title()} '{section_id}' not found in '{path}'" super().__init__(HTTPStatus.NOT_FOUND, detail) def __str__(self) -> str: + """Return a string representation of the exception.""" return self.detail -class STStorageNotFoundError(HTTPException): - """Short-term storage is not found""" +class ThermalClusterNotFound(ConfigSectionNotFound): + """Thermal cluster is not found (404 Not Found)""" - def __init__(self, study_id: str, area_id: str, st_storage_id: str) -> None: - detail = f"Short-term storage '{st_storage_id}' not found in area '{area_id}'" + object_name = THERMAL_CLUSTER + + +class RenewableClusterNotFound(ConfigSectionNotFound): + """Renewable cluster is not found (404 Not Found)""" + + object_name = RENEWABLE_CLUSTER + + +class STStorageNotFound(ConfigSectionNotFound): + """Short-term storage is not found (404 Not Found)""" + + object_name = SHORT_TERM_STORAGE + + +class MatrixNotFound(HTTPException): + """ + Exception raised when a matrix is not found (404 Not Found). + + Notes: + The study ID is not provided because it is implicit. + + Attributes: + path: Path of the missing file(s) relative to the study directory. + """ + + object_name = "" + """Name of the object that is not found: thermal, renewables, etc.""" + + def __init__(self, path: str): + assert _match_input_path(path), f"Invalid path: '{path}'" + self.path = path + detail = f"Matrix '{path}' not found" + if self.object_name: + detail = f"{self.object_name.title()} {detail}" super().__init__(HTTPStatus.NOT_FOUND, detail) def __str__(self) -> str: @@ -63,9 +169,78 @@ def __str__(self) -> str: return self.detail -class UnknownModuleError(Exception): - def __init__(self, message: str) -> None: - super(UnknownModuleError, self).__init__(message) +class ThermalClusterMatrixNotFound(MatrixNotFound): + """Matrix of the thermal cluster is not found (404 Not Found)""" + + object_name = THERMAL_CLUSTER + + +class RenewableClusterMatrixNotFound(MatrixNotFound): + """Matrix of the renewable cluster is not found (404 Not Found)""" + + object_name = RENEWABLE_CLUSTER + + +class STStorageMatrixNotFound(MatrixNotFound): + """Matrix of the short-term storage is not found (404 Not Found)""" + + object_name = SHORT_TERM_STORAGE + + +# ============================================================ +# Duplicate (409) +# ============================================================ + + +class DuplicateConfigSection(HTTPException): + """ + Exception raised when a configuration section is duplicated (409 Conflict). + + Notes: + The study ID is not provided because it is implicit. + + Attributes: + area_id: ID of the area in which the section is duplicated. + duplicates: Sequence of duplicated IDs. + """ + + object_name = "" + """Name of the object that is duplicated: thermal, renewables, etc.""" + + def __init__(self, area_id: str, *duplicates: str): + self.area_id = area_id + self.duplicates = duplicates + ids = ", ".join(f"'{a}'" for a in duplicates) + detail = { + 0: f"Duplicates found in '{area_id}'", + 1: f"Duplicate found in '{area_id}': {ids}", + 2: f"Duplicates found in '{area_id}': {ids}", + }[min(len(duplicates), 2)] + if self.object_name: + detail = f"{self.object_name.title()} {detail}" + super().__init__(HTTPStatus.CONFLICT, detail) + + def __str__(self) -> str: + """Return a string representation of the exception.""" + return self.detail + + +class DuplicateThermalCluster(DuplicateConfigSection): + """Duplicate Thermal cluster (409 Conflict)""" + + object_name = THERMAL_CLUSTER + + +class DuplicateRenewableCluster(DuplicateConfigSection): + """Duplicate Renewable cluster (409 Conflict)""" + + object_name = RENEWABLE_CLUSTER + + +class DuplicateSTStorage(DuplicateConfigSection): + """Duplicate Short-term storage (409 Conflict)""" + + object_name = SHORT_TERM_STORAGE class StudyNotFoundError(HTTPException): @@ -108,11 +283,6 @@ def __init__(self, message: str) -> None: super().__init__(HTTPStatus.LOCKED, message) -class StudyAlreadyExistError(HTTPException): - def __init__(self, message: str) -> None: - super().__init__(HTTPStatus.CONFLICT, message) - - class StudyValidationError(HTTPException): def __init__(self, message: str) -> None: super().__init__(HTTPStatus.UNPROCESSABLE_ENTITY, message) @@ -145,7 +315,7 @@ def __init__(self) -> None: class StudyDeletionNotAllowed(HTTPException): - def __init__(self, uuid: str, message: Optional[str] = None) -> None: + def __init__(self, uuid: str, message: t.Optional[str] = None) -> None: msg = f"Study {uuid} (not managed) is not allowed to be deleted" if message: msg += f"\n{message}" @@ -196,7 +366,7 @@ def __init__(self, message: str) -> None: super().__init__(HTTPStatus.BAD_REQUEST, message) -class BindingConstraintNotFoundError(HTTPException): +class BindingConstraintNotFound(HTTPException): def __init__(self, message: str) -> None: super().__init__(HTTPStatus.NOT_FOUND, message) @@ -206,11 +376,6 @@ def __init__(self, message: str) -> None: super().__init__(HTTPStatus.NOT_FOUND, message) -class ConstraintAlreadyExistError(HTTPException): - def __init__(self, message: str) -> None: - super().__init__(HTTPStatus.NOT_FOUND, message) - - class DuplicateConstraintName(HTTPException): def __init__(self, message: str) -> None: super().__init__(HTTPStatus.CONFLICT, message) @@ -221,15 +386,77 @@ def __init__(self, message: str) -> None: super().__init__(HTTPStatus.BAD_REQUEST, message) -class MissingDataError(HTTPException): +class InvalidFieldForVersionError(HTTPException): def __init__(self, message: str) -> None: - super().__init__(HTTPStatus.NOT_FOUND, message) + super().__init__(HTTPStatus.UNPROCESSABLE_ENTITY, message) + + +class MatrixWidthMismatchError(HTTPException): + def __init__(self, message: str) -> None: + super().__init__(HTTPStatus.UNPROCESSABLE_ENTITY, message) -class ConstraintIdNotFoundError(HTTPException): +class WrongMatrixHeightError(HTTPException): def __init__(self, message: str) -> None: + super().__init__(HTTPStatus.UNPROCESSABLE_ENTITY, message) + + +class ConstraintTermNotFound(HTTPException): + """ + Exception raised when a constraint term is not found. + """ + + def __init__(self, binding_constraint_id: str, *ids: str) -> None: + count = len(ids) + id_enum = ", ".join(f"'{term}'" for term in ids) + message = { + 0: f"Constraint terms not found in BC '{binding_constraint_id}'", + 1: f"Constraint term {id_enum} not found in BC '{binding_constraint_id}'", + 2: f"Constraint terms {id_enum} not found in BC '{binding_constraint_id}'", + }[min(count, 2)] super().__init__(HTTPStatus.NOT_FOUND, message) + def __str__(self) -> str: + """Return a string representation of the exception.""" + return self.detail + + +class DuplicateConstraintTerm(HTTPException): + """ + Exception raised when an attempt is made to create a constraint term which already exists. + """ + + def __init__(self, binding_constraint_id: str, *ids: str) -> None: + count = len(ids) + id_enum = ", ".join(f"'{term}'" for term in ids) + message = { + 0: f"Constraint terms already exist in BC '{binding_constraint_id}'", + 1: f"Constraint term {id_enum} already exists in BC '{binding_constraint_id}'", + 2: f"Constraint terms {id_enum} already exist in BC '{binding_constraint_id}'", + }[min(count, 2)] + super().__init__(HTTPStatus.CONFLICT, message) + + def __str__(self) -> str: + """Return a string representation of the exception.""" + return self.detail + + +class InvalidConstraintTerm(HTTPException): + """ + Exception raised when a constraint term is not correctly specified (no term data). + """ + + def __init__(self, binding_constraint_id: str, term_json: str) -> None: + message = ( + f"Invalid constraint term for binding constraint '{binding_constraint_id}': {term_json}," + f" term 'data' is missing or empty" + ) + super().__init__(HTTPStatus.UNPROCESSABLE_ENTITY, message) + + def __str__(self) -> str: + """Return a string representation of the exception.""" + return self.detail + class LayerNotFound(HTTPException): def __init__(self) -> None: @@ -275,6 +502,14 @@ def __init__(self, *area_ids: str) -> None: super().__init__(HTTPStatus.NOT_FOUND, msg) +class DuplicateAreaName(HTTPException): + """Exception raised when trying to create an area with an already existing name.""" + + def __init__(self, area_name: str) -> None: + msg = f"Area '{area_name}' already exists and could not be created" + super().__init__(HTTPStatus.CONFLICT, msg) + + class DistrictNotFound(HTTPException): def __init__(self, *district_ids: str) -> None: count = len(district_ids) @@ -310,29 +545,3 @@ def __init__(self) -> None: HTTPStatus.BAD_REQUEST, "You cannot scan the default internal workspace", ) - - -class ClusterNotFound(HTTPException): - def __init__(self, cluster_id: str) -> None: - super().__init__( - HTTPStatus.NOT_FOUND, - f"Cluster: '{cluster_id}' not found", - ) - - -class ClusterConfigNotFound(HTTPException): - def __init__(self, area_id: str) -> None: - super().__init__( - HTTPStatus.NOT_FOUND, - f"Cluster configuration for area: '{area_id}' not found", - ) - - -class ClusterAlreadyExists(HTTPException): - """Exception raised when attempting to create a cluster with an already existing ID.""" - - def __init__(self, cluster_type: str, cluster_id: str) -> None: - super().__init__( - HTTPStatus.CONFLICT, - f"{cluster_type} cluster with ID '{cluster_id}' already exists and could not be created.", - ) diff --git a/antarest/core/filesystem_blueprint.py b/antarest/core/filesystem_blueprint.py index 3b15ebd03a..bf247978b2 100644 --- a/antarest/core/filesystem_blueprint.py +++ b/antarest/core/filesystem_blueprint.py @@ -15,7 +15,6 @@ from starlette.responses import PlainTextResponse, StreamingResponse from antarest.core.config import Config -from antarest.core.jwt import JWTUser from antarest.core.utils.web import APITag from antarest.login.auth import Auth diff --git a/antarest/core/filetransfer/service.py b/antarest/core/filetransfer/service.py index 760573a42f..80a81e6927 100644 --- a/antarest/core/filetransfer/service.py +++ b/antarest/core/filetransfer/service.py @@ -43,6 +43,8 @@ def request_download( filename: str, name: Optional[str] = None, owner: Optional[JWTUser] = None, + use_notification: bool = True, + expiration_time_in_minutes: int = 0, ) -> FileDownload: fh, path = tempfile.mkstemp(dir=self.tmp_dir, suffix=filename) os.close(fh) @@ -55,36 +57,40 @@ def request_download( path=str(tmpfile), owner=owner.impersonator if owner is not None else None, expiration_date=datetime.datetime.utcnow() - + datetime.timedelta(minutes=self.download_default_expiration_timeout_minutes), + + datetime.timedelta( + minutes=expiration_time_in_minutes or self.download_default_expiration_timeout_minutes + ), ) self.repository.add(download) - self.event_bus.push( - Event( - type=EventType.DOWNLOAD_CREATED, - payload=download.to_dto(), - permissions=PermissionInfo(owner=owner.impersonator) - if owner - else PermissionInfo(public_mode=PublicMode.READ), + if use_notification: + self.event_bus.push( + Event( + type=EventType.DOWNLOAD_CREATED, + payload=download.to_dto(), + permissions=PermissionInfo(owner=owner.impersonator) + if owner + else PermissionInfo(public_mode=PublicMode.READ), + ) ) - ) return download - def set_ready(self, download_id: str) -> None: + def set_ready(self, download_id: str, use_notification: bool = True) -> None: download = self.repository.get(download_id) if not download: raise FileDownloadNotFound() download.ready = True self.repository.save(download) - self.event_bus.push( - Event( - type=EventType.DOWNLOAD_READY, - payload=download.to_dto(), - permissions=PermissionInfo(owner=download.owner) - if download.owner - else PermissionInfo(public_mode=PublicMode.READ), + if use_notification: + self.event_bus.push( + Event( + type=EventType.DOWNLOAD_READY, + payload=download.to_dto(), + permissions=PermissionInfo(owner=download.owner) + if download.owner + else PermissionInfo(public_mode=PublicMode.READ), + ) ) - ) def fail(self, download_id: str, reason: str = "") -> None: download = self.repository.get(download_id) diff --git a/antarest/launcher/adapters/slurm_launcher/slurm_launcher.py b/antarest/launcher/adapters/slurm_launcher/slurm_launcher.py index d2ce3ad1ec..6aba6f21b3 100644 --- a/antarest/launcher/adapters/slurm_launcher/slurm_launcher.py +++ b/antarest/launcher/adapters/slurm_launcher/slurm_launcher.py @@ -513,22 +513,15 @@ def _apply_params(self, launcher_params: LauncherParametersDTO) -> argparse.Name ): other_options.append("xpansion_sensitivity") - time_limit = launcher_params.time_limit - if time_limit is not None: - if MIN_TIME_LIMIT > time_limit: - logger.warning( - f"Invalid slurm launcher time limit ({time_limit})," - f" should be higher than {MIN_TIME_LIMIT}. Using min limit." - ) - launcher_args.time_limit = MIN_TIME_LIMIT - elif time_limit >= MAX_TIME_LIMIT: - logger.warning( - f"Invalid slurm launcher time limit ({time_limit})," - f" should be lower than {MAX_TIME_LIMIT}. Using max limit." - ) - launcher_args.time_limit = MAX_TIME_LIMIT - 3600 - else: - launcher_args.time_limit = time_limit + # The `time_limit` parameter could be `None`, in that case, the default value is used. + time_limit = launcher_params.time_limit or MIN_TIME_LIMIT + time_limit = min(max(time_limit, MIN_TIME_LIMIT), MAX_TIME_LIMIT) + if launcher_args.time_limit != time_limit: + logger.warning( + f"Invalid slurm launcher time_limit ({time_limit})," + f" should be between {MIN_TIME_LIMIT} and {MAX_TIME_LIMIT}" + ) + launcher_args.time_limit = time_limit post_processing = launcher_params.post_processing if post_processing is not None: diff --git a/antarest/launcher/model.py b/antarest/launcher/model.py index a8f856269d..3bd3427a07 100644 --- a/antarest/launcher/model.py +++ b/antarest/launcher/model.py @@ -25,13 +25,14 @@ class LauncherParametersDTO(BaseModel): adequacy_patch: t.Optional[t.Dict[str, t.Any]] = None nb_cpu: t.Optional[int] = None post_processing: bool = False - time_limit: t.Optional[int] = None # 3600 ≤ time_limit < 864000 (10 days) + time_limit: int = 240 * 3600 # Default value set to 240 hours (in seconds) xpansion: t.Union[XpansionParametersDTO, bool, None] = None xpansion_r_version: bool = False archive_output: bool = True auto_unzip: bool = True output_suffix: t.Optional[str] = None other_options: t.Optional[str] = None + # add extensions field here @classmethod diff --git a/antarest/launcher/service.py b/antarest/launcher/service.py index 023296188b..d3a439e17c 100644 --- a/antarest/launcher/service.py +++ b/antarest/launcher/service.py @@ -40,7 +40,7 @@ from antarest.launcher.repository import JobResultRepository from antarest.launcher.ssh_client import calculates_slurm_load from antarest.launcher.ssh_config import SSHConfigDTO -from antarest.study.repository import StudyFilter +from antarest.study.repository import AccessPermissions, StudyFilter from antarest.study.service import StudyService from antarest.study.storage.utils import assert_permission, extract_output_name, find_single_output_path @@ -312,7 +312,11 @@ def _filter_from_user_permission(self, job_results: List[JobResult], user: Optio if study_ids: studies = { study.id: study - for study in self.study_service.repository.get_all(study_filter=StudyFilter(study_ids=study_ids)) + for study in self.study_service.repository.get_all( + study_filter=StudyFilter( + study_ids=study_ids, access_permissions=AccessPermissions.from_params(user) + ) + ) } else: studies = {} diff --git a/antarest/launcher/web.py b/antarest/launcher/web.py index 051eba2cc4..14eb39aee2 100644 --- a/antarest/launcher/web.py +++ b/antarest/launcher/web.py @@ -231,7 +231,7 @@ def get_solver_versions( "value": "local", }, }, - ) + ), ) -> List[str]: """ Get list of supported solver versions defined in the configuration. @@ -268,7 +268,7 @@ def get_nb_cores( "value": "local", }, }, - ) + ), ) -> Dict[str, int]: """ Retrieve the numer of cores of the launcher. diff --git a/antarest/main.py b/antarest/main.py index 2187088d2b..3973c79ace 100644 --- a/antarest/main.py +++ b/antarest/main.py @@ -61,7 +61,7 @@ class PathType: from antarest.main import PathType parser = argparse.ArgumentParser() - parser.add_argument('--input', type=PathType(file_ok=True, exists=True)) + parser.add_argument("--input", type=PathType(file_ok=True, exists=True)) args = parser.parse_args() print(args.input) diff --git a/antarest/matrixstore/main.py b/antarest/matrixstore/main.py index ddd29c2d36..b59e3eb87a 100644 --- a/antarest/matrixstore/main.py +++ b/antarest/matrixstore/main.py @@ -1,7 +1,6 @@ from typing import Optional from fastapi import FastAPI -from fastapi_jwt_auth.exceptions import AuthJWTException # type: ignore from antarest.core.config import Config from antarest.core.filetransfer.service import FileTransferManager diff --git a/antarest/matrixstore/repository.py b/antarest/matrixstore/repository.py index 9ab44a69ec..8f3e78f082 100644 --- a/antarest/matrixstore/repository.py +++ b/antarest/matrixstore/repository.py @@ -6,8 +6,8 @@ import numpy as np from filelock import FileLock from numpy import typing as npt -from sqlalchemy import and_, exists # type: ignore -from sqlalchemy.orm import Session, aliased # type: ignore +from sqlalchemy import exists # type: ignore +from sqlalchemy.orm import Session # type: ignore from antarest.core.utils.fastapi_sqlalchemy import db from antarest.matrixstore.model import Matrix, MatrixContent, MatrixData, MatrixDataSet diff --git a/antarest/matrixstore/service.py b/antarest/matrixstore/service.py index c0a9d91788..4b4de557f7 100644 --- a/antarest/matrixstore/service.py +++ b/antarest/matrixstore/service.py @@ -3,11 +3,11 @@ import json import logging import tempfile +import typing as t import zipfile from abc import ABC, abstractmethod from datetime import datetime from pathlib import Path -from typing import List, Optional, Sequence, Tuple, Union import numpy as np import py7zr @@ -58,11 +58,11 @@ def __init__(self, matrix_content_repository: MatrixContentRepository) -> None: self.matrix_content_repository = matrix_content_repository @abstractmethod - def create(self, data: Union[List[List[MatrixData]], npt.NDArray[np.float64]]) -> str: + def create(self, data: t.Union[t.List[t.List[MatrixData]], npt.NDArray[np.float64]]) -> str: raise NotImplementedError() @abstractmethod - def get(self, matrix_id: str) -> Optional[MatrixDTO]: + def get(self, matrix_id: str) -> t.Optional[MatrixDTO]: raise NotImplementedError() @abstractmethod @@ -73,12 +73,37 @@ def exists(self, matrix_id: str) -> bool: def delete(self, matrix_id: str) -> None: raise NotImplementedError() + def get_matrix_id(self, matrix: t.Union[t.List[t.List[float]], str]) -> str: + """ + Get the matrix ID from a matrix or a matrix link. + + Args: + matrix: The matrix or matrix link to get the ID from. + + Returns: + The matrix ID. + + Raises: + TypeError: If the provided matrix is neither a matrix nor a link to a matrix. + """ + # noinspection SpellCheckingInspection + if isinstance(matrix, str): + # str.removeprefix() is not available in Python 3.8 + prefix = "matrix://" + if matrix.startswith(prefix): + return matrix[len(prefix) :] + return matrix + elif isinstance(matrix, list): + return self.create(matrix) + else: + raise TypeError(f"Invalid type for matrix: {type(matrix)}") + class SimpleMatrixService(ISimpleMatrixService): def __init__(self, matrix_content_repository: MatrixContentRepository): super().__init__(matrix_content_repository=matrix_content_repository) - def create(self, data: Union[List[List[MatrixData]], npt.NDArray[np.float64]]) -> str: + def create(self, data: t.Union[t.List[t.List[MatrixData]], npt.NDArray[np.float64]]) -> str: return self.matrix_content_repository.save(data) def get(self, matrix_id: str) -> MatrixDTO: @@ -119,7 +144,7 @@ def __init__( self.config = config @staticmethod - def _from_dto(dto: MatrixDTO) -> Tuple[Matrix, MatrixContent]: + def _from_dto(dto: MatrixDTO) -> t.Tuple[Matrix, MatrixContent]: matrix = Matrix( id=dto.id, width=dto.width, @@ -131,7 +156,7 @@ def _from_dto(dto: MatrixDTO) -> Tuple[Matrix, MatrixContent]: return matrix, content - def create(self, data: Union[List[List[MatrixData]], npt.NDArray[np.float64]]) -> str: + def create(self, data: t.Union[t.List[t.List[MatrixData]], npt.NDArray[np.float64]]) -> str: """ Creates a new matrix object with the specified data. @@ -168,7 +193,7 @@ def create(self, data: Union[List[List[MatrixData]], npt.NDArray[np.float64]]) - self.repo.save(matrix) return matrix_id - def create_by_importation(self, file: UploadFile, is_json: bool = False) -> List[MatrixInfoDTO]: + def create_by_importation(self, file: UploadFile, is_json: bool = False) -> t.List[MatrixInfoDTO]: """ Imports a matrix from a TSV or JSON file or a collection of matrices from a ZIP file. @@ -191,7 +216,7 @@ def create_by_importation(self, file: UploadFile, is_json: bool = False) -> List if file.content_type == "application/zip": with contextlib.closing(f): buffer = io.BytesIO(f.read()) - matrix_info: List[MatrixInfoDTO] = [] + matrix_info: t.List[MatrixInfoDTO] = [] if file.filename.endswith("zip"): with zipfile.ZipFile(buffer) as zf: for info in zf.infolist(): @@ -237,7 +262,7 @@ def get_dataset( self, id: str, params: RequestParameters, - ) -> Optional[MatrixDataSet]: + ) -> t.Optional[MatrixDataSet]: if not params.user: raise UserHasNotPermissionError() dataset = self.repo_dataset.get(id) @@ -250,7 +275,7 @@ def get_dataset( def create_dataset( self, dataset_info: MatrixDataSetUpdateDTO, - matrices: List[MatrixInfoDTO], + matrices: t.List[MatrixInfoDTO], params: RequestParameters, ) -> MatrixDataSet: if not params.user: @@ -296,10 +321,10 @@ def update_dataset( def list( self, - dataset_name: Optional[str], + dataset_name: t.Optional[str], filter_own: bool, params: RequestParameters, - ) -> List[MatrixDataSetDTO]: + ) -> t.List[MatrixDataSetDTO]: """ List matrix user metadata @@ -337,7 +362,7 @@ def delete_dataset(self, id: str, params: RequestParameters) -> str: self.repo_dataset.delete(id) return id - def get(self, matrix_id: str) -> Optional[MatrixDTO]: + def get(self, matrix_id: str) -> t.Optional[MatrixDTO]: """ Get a matrix object from the database and the matrix content repository. @@ -414,7 +439,7 @@ def check_access_permission( raise UserHasNotPermissionError() return access - def create_matrix_files(self, matrix_ids: Sequence[str], export_path: Path) -> str: + def create_matrix_files(self, matrix_ids: t.Sequence[str], export_path: Path) -> str: with tempfile.TemporaryDirectory(dir=self.config.storage.tmp_dir) as tmpdir: stopwatch = StopWatch() for mid in matrix_ids: @@ -461,7 +486,7 @@ def download_dataset( def download_matrix_list( self, - matrix_list: Sequence[str], + matrix_list: t.Sequence[str], dataset_name: str, params: RequestParameters, ) -> FileDownloadTaskDTO: diff --git a/antarest/study/business/advanced_parameters_management.py b/antarest/study/business/advanced_parameters_management.py index 6cd0825322..f18e47a71f 100644 --- a/antarest/study/business/advanced_parameters_management.py +++ b/antarest/study/business/advanced_parameters_management.py @@ -91,7 +91,7 @@ def check_accuracy_on_correlation(cls, v: str) -> str: return "" allowed_values = ["wind", "load", "solar"] - values_list = re.split("\s*,\s*", v.strip()) + values_list = re.split(r"\s*,\s*", v.strip()) if len(values_list) != len(set(values_list)): raise ValueError("Duplicate value") diff --git a/antarest/study/business/all_optional_meta.py b/antarest/study/business/all_optional_meta.py new file mode 100644 index 0000000000..06ddc012d8 --- /dev/null +++ b/antarest/study/business/all_optional_meta.py @@ -0,0 +1,94 @@ +import typing as t + +import pydantic.fields +import pydantic.main +from pydantic import BaseModel + +from antarest.core.utils.string import to_camel_case + + +class AllOptionalMetaclass(pydantic.main.ModelMetaclass): + """ + Metaclass that makes all fields of a Pydantic model optional. + + Usage: + class MyModel(BaseModel, metaclass=AllOptionalMetaclass): + field1: str + field2: int + ... + + Instances of the model can be created even if not all fields are provided during initialization. + Default values, when provided, are used unless `use_none` is set to `True`. + """ + + def __new__( + cls: t.Type["AllOptionalMetaclass"], + name: str, + bases: t.Tuple[t.Type[t.Any], ...], + namespaces: t.Dict[str, t.Any], + use_none: bool = False, + **kwargs: t.Dict[str, t.Any], + ) -> t.Any: + """ + Create a new instance of the metaclass. + + Args: + name: Name of the class to create. + bases: Base classes of the class to create (a Pydantic model). + namespaces: namespace of the class to create that defines the fields of the model. + use_none: If `True`, the default value of the fields is set to `None`. + Note that this field is not part of the Pydantic model, but it is an extension. + **kwargs: Additional keyword arguments used by the metaclass. + """ + # Modify the annotations of the class (but not of the ancestor classes) + # in order to make all fields optional. + # If the current model inherits from another model, the annotations of the ancestor models + # are not modified, because the fields are already converted to `ModelField`. + annotations = namespaces.get("__annotations__", {}) + for field_name, field_type in annotations.items(): + if not field_name.startswith("__"): + # Making already optional fields optional is not a problem (nothing is changed). + annotations[field_name] = t.Optional[field_type] + namespaces["__annotations__"] = annotations + + if use_none: + # Modify the namespace fields to set their default value to `None`. + for field_name, field_info in namespaces.items(): + if isinstance(field_info, pydantic.fields.FieldInfo): + field_info.default = None + field_info.default_factory = None + + # Create the class: all annotations are converted into `ModelField`. + instance = super().__new__(cls, name, bases, namespaces, **kwargs) + + # Modify the inherited fields of the class to make them optional + # and set their default value to `None`. + model_field: pydantic.fields.ModelField + for field_name, model_field in instance.__fields__.items(): + model_field.required = False + model_field.allow_none = True + if use_none: + model_field.default = None + model_field.default_factory = None + model_field.field_info.default = None + + return instance + + +MODEL = t.TypeVar("MODEL", bound=t.Type[BaseModel]) + + +def camel_case_model(model: MODEL) -> MODEL: + """ + This decorator can be used to modify a model to use camel case aliases. + + Args: + model: The pydantic model to modify. + + Returns: + The modified model. + """ + model.__config__.alias_generator = to_camel_case + for field_name, field in model.__fields__.items(): + field.alias = to_camel_case(field_name) + return model diff --git a/antarest/study/business/area_management.py b/antarest/study/business/area_management.py index 369b5a96ad..8f0758d9dc 100644 --- a/antarest/study/business/area_management.py +++ b/antarest/study/business/area_management.py @@ -1,15 +1,24 @@ +import enum import logging import re -from enum import Enum -from typing import Any, Dict, List, Optional, Sequence, Tuple +import typing as t -from pydantic import BaseModel +from pydantic import BaseModel, Extra, Field -from antarest.core.exceptions import LayerNotAllowedToBeDeleted, LayerNotFound +from antarest.core.exceptions import ConfigFileNotFound, DuplicateAreaName, LayerNotAllowedToBeDeleted, LayerNotFound +from antarest.core.model import JSON +from antarest.study.business.all_optional_meta import AllOptionalMetaclass, camel_case_model from antarest.study.business.utils import execute_or_add_commands from antarest.study.model import Patch, PatchArea, PatchCluster, RawStudy, Study from antarest.study.repository import StudyMetadataRepository from antarest.study.storage.patch_service import PatchService +from antarest.study.storage.rawstudy.model.filesystem.config.area import ( + AdequacyPathProperties, + AreaFolder, + OptimizationProperties, + ThermalAreasProperties, + UIProperties, +) from antarest.study.storage.rawstudy.model.filesystem.config.model import Area, DistrictSet, transform_name_to_id from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy from antarest.study.storage.storage_service import StudyStorageService @@ -21,7 +30,7 @@ logger = logging.getLogger(__name__) -class AreaType(Enum): +class AreaType(enum.Enum): AREA = "AREA" DISTRICT = "DISTRICT" @@ -29,44 +38,86 @@ class AreaType(Enum): class AreaCreationDTO(BaseModel): name: str type: AreaType - metadata: Optional[PatchArea] - set: Optional[List[str]] + metadata: t.Optional[PatchArea] + set: t.Optional[t.List[str]] +# review: is this class necessary? class ClusterInfoDTO(PatchCluster): id: str name: str enabled: bool = True unitcount: int = 0 nominalcapacity: int = 0 - group: Optional[str] = None - min_stable_power: Optional[int] = None - min_up_time: Optional[int] = None - min_down_time: Optional[int] = None - spinning: Optional[float] = None - marginal_cost: Optional[float] = None - spread_cost: Optional[float] = None - market_bid_cost: Optional[float] = None + group: t.Optional[str] = None + min_stable_power: t.Optional[int] = None + min_up_time: t.Optional[int] = None + min_down_time: t.Optional[int] = None + spinning: t.Optional[float] = None + marginal_cost: t.Optional[float] = None + spread_cost: t.Optional[float] = None + market_bid_cost: t.Optional[float] = None class AreaInfoDTO(AreaCreationDTO): id: str - thermals: Optional[List[ClusterInfoDTO]] = None - - -class AreaUI(BaseModel): - x: int - y: int - color_rgb: Tuple[int, int, int] + thermals: t.Optional[t.List[ClusterInfoDTO]] = None class LayerInfoDTO(BaseModel): id: str name: str - areas: List[str] + areas: t.List[str] + +class UpdateAreaUi(BaseModel, extra="forbid", allow_population_by_field_name=True): + """ + DTO for updating area UI + + Usage: + + >>> from antarest.study.business.area_management import UpdateAreaUi + >>> from pprint import pprint + + >>> obj = { + ... "x": -673.75, + ... "y": 301.5, + ... "color_rgb": [230, 108, 44], + ... "layerX": {"0": -230, "4": -230, "6": -95, "7": -230, "8": -230}, + ... "layerY": {"0": 136, "4": 136, "6": 39, "7": 136, "8": 136}, + ... "layerColor": { + ... "0": "230, 108, 44", + ... "4": "230, 108, 44", + ... "6": "230, 108, 44", + ... "7": "230, 108, 44", + ... "8": "230, 108, 44", + ... }, + ... } + + >>> model = UpdateAreaUi(**obj) + >>> pprint(model.dict(by_alias=True), width=80) + {'colorRgb': [230, 108, 44], + 'layerColor': {0: '230, 108, 44', + 4: '230, 108, 44', + 6: '230, 108, 44', + 7: '230, 108, 44', + 8: '230, 108, 44'}, + 'layerX': {0: -230, 4: -230, 6: -95, 7: -230, 8: -230}, + 'layerY': {0: 136, 4: 136, 6: 39, 7: 136, 8: 136}, + 'x': -673, + 'y': 301} -def _get_ui_info_map(file_study: FileStudy, area_ids: Sequence[str]) -> Dict[str, Any]: + """ + + x: int = Field(title="X position") + y: int = Field(title="Y position") + color_rgb: t.Sequence[int] = Field(title="RGB color", alias="colorRgb") + layer_x: t.Mapping[int, int] = Field(default_factory=dict, title="X position of each layer", alias="layerX") + layer_y: t.Mapping[int, int] = Field(default_factory=dict, title="Y position of each layer", alias="layerY") + layer_color: t.Mapping[int, str] = Field(default_factory=dict, title="Color of each layer", alias="layerColor") + + +def _get_ui_info_map(file_study: FileStudy, area_ids: t.Sequence[str]) -> t.Dict[str, t.Any]: """ Get the UI information (a JSON object) for each selected Area. @@ -84,7 +135,9 @@ def _get_ui_info_map(file_study: FileStudy, area_ids: Sequence[str]) -> Dict[str # instead of raising an obscure exception. if not area_ids: return {} + ui_info_map = file_study.tree.get(["input", "areas", ",".join(area_ids), "ui"]) + # If there is only one ID in the `area_ids`, the result returned from # the `file_study.tree.get` call will be a single UI object. # On the other hand, if there are multiple values in `area_ids`, @@ -92,25 +145,258 @@ def _get_ui_info_map(file_study: FileStudy, area_ids: Sequence[str]) -> Dict[str # and the values are the corresponding UI objects. if len(area_ids) == 1: ui_info_map = {area_ids[0]: ui_info_map} + + # Convert to UIProperties to ensure that the UI object is valid. + ui_info_map = {area_id: UIProperties(**ui_info).to_config() for area_id, ui_info in ui_info_map.items()} + return ui_info_map -def _get_area_layers(area_uis: Dict[str, Any], area: str) -> List[str]: +def _get_area_layers(area_uis: t.Dict[str, t.Any], area: str) -> t.List[str]: if area in area_uis and "ui" in area_uis[area] and "layers" in area_uis[area]["ui"]: return re.split(r"\s+", (str(area_uis[area]["ui"]["layers"]) or "")) return [] +_ALL_AREAS_PATH = "input/areas" +_THERMAL_AREAS_PATH = "input/thermal/areas" + + +# noinspection SpellCheckingInspection +class _BaseAreaDTO( + OptimizationProperties.FilteringSection, + OptimizationProperties.ModalOptimizationSection, + AdequacyPathProperties.AdequacyPathSection, + extra=Extra.forbid, + validate_assignment=True, + allow_population_by_field_name=True, +): + """ + Represents an area output. + + Aggregates the fields of the `OptimizationProperties` and `AdequacyPathProperties` classes, + but without the `UIProperties` fields. + + Add the fields extracted from the `/input/thermal/areas.ini` information: + + - `average_unsupplied_energy_cost` is extracted from `unserverd_energy_cost`, + - `average_spilled_energy_cost` is extracted from `spilled_energy_cost`. + """ + + average_unsupplied_energy_cost: float = Field(0.0, description="average unserverd energy cost (€/MWh)") + average_spilled_energy_cost: float = Field(0.0, description="average spilled energy cost (€/MWh)") + + +# noinspection SpellCheckingInspection +@camel_case_model +class AreaOutput(_BaseAreaDTO, metaclass=AllOptionalMetaclass, use_none=True): + """ + DTO object use to get the area information using a flat structure. + """ + + @classmethod + def from_model( + cls, + area_folder: AreaFolder, + *, + average_unsupplied_energy_cost: float, + average_spilled_energy_cost: float, + ) -> "AreaOutput": + """ + Creates a `GetAreaDTO` object from configuration data. + + Args: + area_folder: Configuration data read from the `/input/areas/` information. + average_unsupplied_energy_cost: Unserverd energy cost (€/MWh). + average_spilled_energy_cost: Spilled energy cost (€/MWh). + Returns: + The `GetAreaDTO` object. + """ + obj = { + "average_unsupplied_energy_cost": average_unsupplied_energy_cost, + "average_spilled_energy_cost": average_spilled_energy_cost, + **area_folder.optimization.filtering.dict(by_alias=False), + **area_folder.optimization.nodal_optimization.dict(by_alias=False), + # adequacy_patch is only available if study version >= 830. + **(area_folder.adequacy_patch.adequacy_patch.dict(by_alias=False) if area_folder.adequacy_patch else {}), + } + return cls(**obj) + + def _to_optimization(self) -> OptimizationProperties: + obj = {name: getattr(self, name) for name in OptimizationProperties.FilteringSection.__fields__} + filtering_section = OptimizationProperties.FilteringSection(**obj) + obj = {name: getattr(self, name) for name in OptimizationProperties.ModalOptimizationSection.__fields__} + nodal_optimization_section = OptimizationProperties.ModalOptimizationSection(**obj) + return OptimizationProperties( + filtering=filtering_section, + nodal_optimization=nodal_optimization_section, + ) + + def _to_adequacy_patch(self) -> t.Optional[AdequacyPathProperties]: + obj = {name: getattr(self, name) for name in AdequacyPathProperties.AdequacyPathSection.__fields__} + # If all fields are `None`, the object is empty. + if all(value is None for value in obj.values()): + return None + adequacy_path_section = AdequacyPathProperties.AdequacyPathSection(**obj) + return AdequacyPathProperties(adequacy_patch=adequacy_path_section) + + @property + def area_folder(self) -> AreaFolder: + area_folder = AreaFolder( + optimization=self._to_optimization(), + adequacy_patch=self._to_adequacy_patch(), + # UI properties are not configurable in Table Mode + ) + return area_folder + + class AreaManager: + """ + Manages operations related to areas in a study, including retrieval, creation, and updates. + + Attributes: + storage_service: The service responsible for study storage operations. + patch_service: The service responsible for study patch operations. + This service is used to store additional data for each area, in particular the country + of origin (`country`) and a list of tags for searching (`tags`). + """ + def __init__( self, storage_service: StudyStorageService, repository: StudyMetadataRepository, ) -> None: + """ + Initializes the AreaManager. + + Args: + storage_service: The service responsible for study storage operations. + repository: The repository for study metadata operations. + """ self.storage_service = storage_service self.patch_service = PatchService(repository=repository) - def get_all_areas(self, study: RawStudy, area_type: Optional[AreaType] = None) -> List[AreaInfoDTO]: + # noinspection SpellCheckingInspection + def get_all_area_props(self, study: RawStudy) -> t.Mapping[str, AreaOutput]: + """ + Retrieves all areas of a study. + + Args: + study: The raw study object. + Returns: + A mapping of area IDs to area properties. + Raises: + ConfigFileNotFound: if a configuration file is not found. + """ + file_study = self.storage_service.get_storage(study).get_raw(study) + + # Get the area information from the `/input/areas/` file. + path = _ALL_AREAS_PATH + try: + areas_cfg = file_study.tree.get(path.split("/"), depth=5) + except KeyError: + raise ConfigFileNotFound(path) from None + else: + # "list" and "sets" must be removed: we only need areas. + areas_cfg.pop("list", None) + areas_cfg.pop("sets", None) + + # Get the unserverd and spilled energy costs from the `/input/thermal/areas.ini` file. + path = _THERMAL_AREAS_PATH + try: + thermal_cfg = file_study.tree.get(path.split("/"), depth=3) + except KeyError: + raise ConfigFileNotFound(path) from None + else: + thermal_areas = ThermalAreasProperties(**thermal_cfg) + + # areas_cfg contains a dictionary where the keys are the area IDs, + # and the values are objects that can be converted to `AreaFolder`. + area_map = {} + for area_id, area_cfg in areas_cfg.items(): + area_folder = AreaFolder(**area_cfg) + area_map[area_id] = AreaOutput.from_model( + area_folder, + average_unsupplied_energy_cost=thermal_areas.unserverd_energy_cost.get(area_id, 0.0), + average_spilled_energy_cost=thermal_areas.spilled_energy_cost.get(area_id, 0.0), + ) + + return area_map + + # noinspection SpellCheckingInspection + def update_areas_props( + self, study: RawStudy, update_areas_by_ids: t.Mapping[str, AreaOutput] + ) -> t.Mapping[str, AreaOutput]: + """ + Update the properties of ares. + + Args: + study: The raw study object. + update_areas_by_ids: A mapping of area IDs to area properties. + + Returns: + A mapping of ALL area IDs to area properties. + """ + old_areas_by_ids = self.get_all_area_props(study) + new_areas_by_ids = {k: v for k, v in old_areas_by_ids.items()} + + # Prepare the commands to update the thermal clusters. + commands = [] + command_context = self.storage_service.variant_study_service.command_factory.command_context + + for area_id, update_area in update_areas_by_ids.items(): + # Update the area properties. + old_area = old_areas_by_ids[area_id] + new_area = old_area.copy(update=update_area.dict(by_alias=False, exclude_none=True)) + new_areas_by_ids[area_id] = new_area + + # Convert the DTO to a configuration object and update the configuration file. + old_area_folder = old_area.area_folder + new_area_folder = new_area.area_folder + + if old_area_folder.optimization != new_area_folder.optimization: + commands.append( + UpdateConfig( + target=f"input/areas/{area_id}/optimization", + data=new_area_folder.optimization.to_config(), + command_context=command_context, + ) + ) + if old_area_folder.adequacy_patch != new_area_folder.adequacy_patch and new_area_folder.adequacy_patch: + commands.append( + UpdateConfig( + target=f"input/areas/{area_id}/adequacy_patch", + data=new_area_folder.adequacy_patch.to_config(), + command_context=command_context, + ) + ) + if old_area.average_unsupplied_energy_cost != new_area.average_unsupplied_energy_cost: + commands.append( + UpdateConfig( + target=f"input/thermal/areas/unserverdenergycost/{area_id}", + data=new_area.average_unsupplied_energy_cost, + command_context=command_context, + ) + ) + if old_area.average_spilled_energy_cost != new_area.average_spilled_energy_cost: + commands.append( + UpdateConfig( + target=f"input/thermal/areas/spilledenergycost:{area_id}", + data=new_area.average_spilled_energy_cost, + command_context=command_context, + ) + ) + + file_study = self.storage_service.get_storage(study).get_raw(study) + execute_or_add_commands(study, file_study, commands, self.storage_service) + + return new_areas_by_ids + + @staticmethod + def get_table_schema() -> JSON: + return AreaOutput.schema() + + def get_all_areas(self, study: RawStudy, area_type: t.Optional[AreaType] = None) -> t.List[AreaInfoDTO]: """ Retrieves all areas and districts of a raw study based on the area type. @@ -124,9 +410,9 @@ def get_all_areas(self, study: RawStudy, area_type: Optional[AreaType] = None) - storage_service = self.storage_service.get_storage(study) file_study = storage_service.get_raw(study) metadata = self.patch_service.get(study) - areas_metadata: Dict[str, PatchArea] = metadata.areas or {} - cfg_areas: Dict[str, Area] = file_study.config.areas - result: List[AreaInfoDTO] = [] + areas_metadata: t.Dict[str, PatchArea] = metadata.areas or {} + cfg_areas: t.Dict[str, Area] = file_study.config.areas + result: t.List[AreaInfoDTO] = [] if area_type is None or area_type == AreaType.AREA: result.extend( @@ -141,7 +427,7 @@ def get_all_areas(self, study: RawStudy, area_type: Optional[AreaType] = None) - ) if area_type is None or area_type == AreaType.DISTRICT: - cfg_sets: Dict[str, DistrictSet] = file_study.config.sets + cfg_sets: t.Dict[str, DistrictSet] = file_study.config.sets result.extend( AreaInfoDTO( id=set_id, @@ -155,7 +441,7 @@ def get_all_areas(self, study: RawStudy, area_type: Optional[AreaType] = None) - return result - def get_all_areas_ui_info(self, study: RawStudy) -> Dict[str, Any]: + def get_all_areas_ui_info(self, study: RawStudy) -> t.Dict[str, t.Any]: """ Retrieve information about all areas' user interface (UI) from the study. @@ -173,7 +459,7 @@ def get_all_areas_ui_info(self, study: RawStudy) -> Dict[str, Any]: area_ids = list(file_study.config.areas) return _get_ui_info_map(file_study, area_ids) - def get_layers(self, study: RawStudy) -> List[LayerInfoDTO]: + def get_layers(self, study: RawStudy) -> t.List[LayerInfoDTO]: storage_service = self.storage_service.get_storage(study) file_study = storage_service.get_raw(study) area_ids = list(file_study.config.areas) @@ -196,7 +482,7 @@ def get_layers(self, study: RawStudy) -> List[LayerInfoDTO]: for layer in layers ] - def update_layer_areas(self, study: RawStudy, layer_id: str, areas: List[str]) -> None: + def update_layer_areas(self, study: RawStudy, layer_id: str, areas: t.List[str]) -> None: logger.info(f"Updating layer {layer_id} with areas {areas}") file_study = self.storage_service.get_storage(study).get_raw(study) layers = file_study.tree.get(["layers", "layers", "layers"]) @@ -213,9 +499,9 @@ def update_layer_areas(self, study: RawStudy, layer_id: str, areas: List[str]) - ] to_remove_areas = [area for area in existing_areas if area not in areas] to_add_areas = [area for area in areas if area not in existing_areas] - commands: List[ICommand] = [] + commands: t.List[ICommand] = [] - def create_update_commands(area_id: str) -> List[ICommand]: + def create_update_commands(area_id: str) -> t.List[ICommand]: return [ UpdateConfig( target=f"input/areas/{area_id}/ui/layerX", @@ -235,7 +521,7 @@ def create_update_commands(area_id: str) -> List[ICommand]: ] for area in to_remove_areas: - area_to_remove_layers: List[str] = _get_area_layers(areas_ui, area) + area_to_remove_layers: t.List[str] = _get_area_layers(areas_ui, area) if layer_id in areas_ui[area]["layerX"]: del areas_ui[area]["layerX"][layer_id] if layer_id in areas_ui[area]["layerY"]: @@ -246,7 +532,7 @@ def create_update_commands(area_id: str) -> List[ICommand]: ) commands.extend(create_update_commands(area)) for area in to_add_areas: - area_to_add_layers: List[str] = _get_area_layers(areas_ui, area) + area_to_add_layers: t.List[str] = _get_area_layers(areas_ui, area) if layer_id not in areas_ui[area]["layerX"]: areas_ui[area]["layerX"][layer_id] = areas_ui[area]["ui"]["x"] if layer_id not in areas_ui[area]["layerY"]: @@ -318,12 +604,20 @@ def remove_layer(self, study: RawStudy, layer_id: str) -> None: def create_area(self, study: Study, area_creation_info: AreaCreationDTO) -> AreaInfoDTO: file_study = self.storage_service.get_storage(study).get_raw(study) + + # check if area already exists + area_id = transform_name_to_id(area_creation_info.name) + if area_id in set(file_study.config.areas): + raise DuplicateAreaName(area_creation_info.name) + + # Create area and apply changes in the study command = CreateArea( area_name=area_creation_info.name, command_context=self.storage_service.variant_study_service.command_factory.command_context, ) execute_or_add_commands(study, file_study, [command], self.storage_service) - area_id = transform_name_to_id(area_creation_info.name) + + # Update metadata patch = self.patch_service.get(study) patch.areas = patch.areas or {} patch.areas[area_id] = area_creation_info.metadata or PatchArea() @@ -357,33 +651,40 @@ def update_area_metadata( set=area_or_set.get_areas(list(file_study.config.areas)) if isinstance(area_or_set, DistrictSet) else [], ) - def update_area_ui(self, study: Study, area_id: str, area_ui: AreaUI, layer: str = "0") -> None: + def update_area_ui(self, study: Study, area_id: str, area_ui: UpdateAreaUi, layer: str = "0") -> None: + obj = { + "x": area_ui.x, + "y": area_ui.y, + "color_r": area_ui.color_rgb[0], + "color_g": area_ui.color_rgb[1], + "color_b": area_ui.color_rgb[2], + } file_study = self.storage_service.get_storage(study).get_raw(study) commands = ( [ UpdateConfig( target=f"input/areas/{area_id}/ui/ui/x", - data=area_ui.x, + data=obj["x"], command_context=self.storage_service.variant_study_service.command_factory.command_context, ), UpdateConfig( target=f"input/areas/{area_id}/ui/ui/y", - data=area_ui.y, + data=obj["y"], command_context=self.storage_service.variant_study_service.command_factory.command_context, ), UpdateConfig( target=f"input/areas/{area_id}/ui/ui/color_r", - data=area_ui.color_rgb[0], + data=obj["color_r"], command_context=self.storage_service.variant_study_service.command_factory.command_context, ), UpdateConfig( target=f"input/areas/{area_id}/ui/ui/color_g", - data=area_ui.color_rgb[1], + data=obj["color_g"], command_context=self.storage_service.variant_study_service.command_factory.command_context, ), UpdateConfig( target=f"input/areas/{area_id}/ui/ui/color_b", - data=area_ui.color_rgb[2], + data=obj["color_b"], command_context=self.storage_service.variant_study_service.command_factory.command_context, ), ] @@ -394,17 +695,17 @@ def update_area_ui(self, study: Study, area_id: str, area_ui: AreaUI, layer: str [ UpdateConfig( target=f"input/areas/{area_id}/ui/layerX/{layer}", - data=area_ui.x, + data=obj["x"], command_context=self.storage_service.variant_study_service.command_factory.command_context, ), UpdateConfig( target=f"input/areas/{area_id}/ui/layerY/{layer}", - data=area_ui.y, + data=obj["y"], command_context=self.storage_service.variant_study_service.command_factory.command_context, ), UpdateConfig( target=f"input/areas/{area_id}/ui/layerColor/{layer}", - data=f"{str(area_ui.color_rgb[0])} , {str(area_ui.color_rgb[1])} , {str(area_ui.color_rgb[2])}", + data=f"{obj['color_r']},{obj['color_g']},{obj['color_b']}", command_context=self.storage_service.variant_study_service.command_factory.command_context, ), ] @@ -415,7 +716,7 @@ def update_thermal_cluster_metadata( self, study: Study, area_id: str, - clusters_metadata: Dict[str, PatchCluster], + clusters_metadata: t.Dict[str, PatchCluster], ) -> AreaInfoDTO: file_study = self.storage_service.get_storage(study).get_raw(study) patch = self.patch_service.get(study) @@ -444,7 +745,7 @@ def delete_area(self, study: Study, area_id: str) -> None: def _update_with_cluster_metadata( area: str, info: ClusterInfoDTO, - cluster_patch: Dict[str, PatchCluster], + cluster_patch: t.Dict[str, PatchCluster], ) -> ClusterInfoDTO: patch = cluster_patch.get(f"{area}.{info.id}", PatchCluster()) info.code_oi = patch.code_oi @@ -452,14 +753,11 @@ def _update_with_cluster_metadata( return info @staticmethod - def _get_clusters(file_study: FileStudy, area: str, metadata_patch: Patch) -> List[ClusterInfoDTO]: + def _get_clusters(file_study: FileStudy, area: str, metadata_patch: Patch) -> t.List[ClusterInfoDTO]: thermal_clusters_data = file_study.tree.get(["input", "thermal", "clusters", area, "list"]) cluster_patch = metadata_patch.thermal_clusters or {} - return [ - AreaManager._update_with_cluster_metadata( - area, - ClusterInfoDTO.parse_obj({**thermal_clusters_data[tid], "id": tid}), - cluster_patch, - ) - for tid in thermal_clusters_data + result = [ + AreaManager._update_with_cluster_metadata(area, ClusterInfoDTO(id=tid, **obj), cluster_patch) + for tid, obj in thermal_clusters_data.items() ] + return result diff --git a/antarest/study/business/areas/properties_management.py b/antarest/study/business/areas/properties_management.py index 1c18ca2b45..2014c554dc 100644 --- a/antarest/study/business/areas/properties_management.py +++ b/antarest/study/business/areas/properties_management.py @@ -2,39 +2,23 @@ from builtins import sorted from typing import Any, Dict, Iterable, List, Optional, Set, cast -from pydantic import Field, root_validator +from pydantic import root_validator -from antarest.study.business.enum_ignore_case import EnumIgnoreCase from antarest.study.business.utils import FieldInfo, FormFieldsBaseModel, execute_or_add_commands from antarest.study.model import Study +from antarest.study.storage.rawstudy.model.filesystem.config.area import AdequacyPatchMode from antarest.study.storage.rawstudy.model.filesystem.folder_node import ChildNotFoundError from antarest.study.storage.storage_service import StudyStorageService from antarest.study.storage.variantstudy.model.command.update_config import UpdateConfig AREA_PATH = "input/areas/{area}" THERMAL_PATH = "input/thermal/areas/{field}/{{area}}" -UI_PATH = f"{AREA_PATH}/ui/ui" OPTIMIZATION_PATH = f"{AREA_PATH}/optimization" NODAL_OPTIMIZATION_PATH = f"{OPTIMIZATION_PATH}/nodal optimization" FILTERING_PATH = f"{OPTIMIZATION_PATH}/filtering" # Keep the order FILTER_OPTIONS = ["hourly", "daily", "weekly", "monthly", "annual"] DEFAULT_FILTER_VALUE = FILTER_OPTIONS -DEFAULT_UI = { - "color_r": 230, - "color_g": 108, - "color_b": 44, -} - - -def encode_color(ui: Dict[str, Any]) -> str: - data = {**DEFAULT_UI, **ui} - return f"{data['color_r']},{data['color_g']},{data['color_b']}" - - -def decode_color(encoded_color: str, current_ui: Optional[Dict[str, int]]) -> Dict[str, Any]: - r, g, b = map(int, encoded_color.split(",")) - return {**(current_ui or {}), "color_r": r, "color_g": g, "color_b": b} def sort_filter_options(options: Iterable[str]) -> List[str]: @@ -53,16 +37,7 @@ def decode_filter(encoded_value: Set[str], current_filter: Optional[str] = None) return ", ".join(sort_filter_options(encoded_value)) -class AdequacyPatchMode(EnumIgnoreCase): - OUTSIDE = "outside" - INSIDE = "inside" - VIRTUAL = "virtual" - - class PropertiesFormFields(FormFieldsBaseModel): - color: Optional[str] = Field(regex="^\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*$") - pos_x: Optional[float] - pos_y: Optional[float] energy_cost_unsupplied: Optional[float] energy_cost_spilled: Optional[float] non_dispatch_power: Optional[bool] @@ -89,21 +64,6 @@ def validation(cls, values: Dict[str, Any]) -> Dict[str, Any]: FIELDS_INFO: Dict[str, FieldInfo] = { - # `color` must be before `pos_x` and `pos_y`, because they are include in the `decode_color`'s return dict value - "color": { - "path": UI_PATH, - "encode": encode_color, - "decode": decode_color, - "default_value": encode_color(DEFAULT_UI), - }, - "pos_x": { - "path": f"{UI_PATH}/x", - "default_value": 0.0, - }, - "pos_y": { - "path": f"{UI_PATH}/y", - "default_value": 0.0, - }, "energy_cost_unsupplied": { "path": THERMAL_PATH.format(field="unserverdenergycost"), "default_value": 0.0, diff --git a/antarest/study/business/areas/renewable_management.py b/antarest/study/business/areas/renewable_management.py index c4152924bf..1009c9d22c 100644 --- a/antarest/study/business/areas/renewable_management.py +++ b/antarest/study/business/areas/renewable_management.py @@ -1,11 +1,14 @@ +import collections import json import typing as t from pydantic import validator -from antarest.core.exceptions import ClusterAlreadyExists, ClusterConfigNotFound, ClusterNotFound +from antarest.core.exceptions import DuplicateRenewableCluster, RenewableClusterConfigNotFound, RenewableClusterNotFound +from antarest.core.model import JSON +from antarest.study.business.all_optional_meta import AllOptionalMetaclass, camel_case_model from antarest.study.business.enum_ignore_case import EnumIgnoreCase -from antarest.study.business.utils import AllOptionalMetaclass, camel_case_model, execute_or_add_commands +from antarest.study.business.utils import execute_or_add_commands from antarest.study.model import Study from antarest.study.storage.rawstudy.model.filesystem.config.model import transform_name_to_id from antarest.study.storage.rawstudy.model.filesystem.config.renewable import ( @@ -21,16 +24,9 @@ from antarest.study.storage.variantstudy.model.command.replace_matrix import ReplaceMatrix from antarest.study.storage.variantstudy.model.command.update_config import UpdateConfig -__all__ = ( - "RenewableClusterInput", - "RenewableClusterCreation", - "RenewableClusterOutput", - "RenewableManager", - "TimeSeriesInterpretation", -) - _CLUSTER_PATH = "input/renewables/clusters/{area_id}/list/{cluster_id}" _CLUSTERS_PATH = "input/renewables/clusters/{area_id}/list" +_ALL_CLUSTERS_PATH = "input/renewables/clusters" class TimeSeriesInterpretation(EnumIgnoreCase): @@ -132,7 +128,7 @@ def get_clusters(self, study: Study, area_id: str) -> t.Sequence[RenewableCluste List of cluster output for all clusters. Raises: - ClusterConfigNotFound: If the clusters configuration for the specified area is not found. + RenewableClusterConfigNotFound: If the clusters configuration for the specified area is not found. """ file_study = self._get_file_study(study) path = _CLUSTERS_PATH.format(area_id=area_id) @@ -140,10 +136,46 @@ def get_clusters(self, study: Study, area_id: str) -> t.Sequence[RenewableCluste try: clusters = file_study.tree.get(path.split("/"), depth=3) except KeyError: - raise ClusterConfigNotFound(area_id) + raise RenewableClusterConfigNotFound(path, area_id) return [create_renewable_output(study.version, cluster_id, cluster) for cluster_id, cluster in clusters.items()] + def get_all_renewables_props( + self, + study: Study, + ) -> t.Mapping[str, t.Mapping[str, RenewableClusterOutput]]: + """ + Retrieve all renewable clusters from all areas within a study. + + Args: + study: Study from which to retrieve the clusters. + + Returns: + A mapping of area IDs to a mapping of cluster IDs to cluster output. + + Raises: + RenewableClusterConfigNotFound: If no clusters are found in the specified area. + """ + + file_study = self._get_file_study(study) + path = _ALL_CLUSTERS_PATH + try: + # may raise KeyError if the path is missing + clusters = file_study.tree.get(path.split("/"), depth=5) + # may raise KeyError if "list" is missing + clusters = {area_id: cluster_list["list"] for area_id, cluster_list in clusters.items()} + except KeyError: + raise RenewableClusterConfigNotFound(path) + + study_version = study.version + renewables_by_areas: t.MutableMapping[str, t.MutableMapping[str, RenewableClusterOutput]] + renewables_by_areas = collections.defaultdict(dict) + for area_id, cluster_obj in clusters.items(): + for cluster_id, cluster in cluster_obj.items(): + renewables_by_areas[area_id][cluster_id] = create_renewable_output(study_version, cluster_id, cluster) + + return renewables_by_areas + def create_cluster( self, study: Study, area_id: str, cluster_data: RenewableClusterCreation ) -> RenewableClusterOutput: @@ -192,14 +224,14 @@ def get_cluster(self, study: Study, area_id: str, cluster_id: str) -> RenewableC The cluster output representation. Raises: - ClusterNotFound: If the specified cluster is not found within the area. + RenewableClusterNotFound: If the specified cluster is not found within the area. """ file_study = self._get_file_study(study) path = _CLUSTER_PATH.format(area_id=area_id, cluster_id=cluster_id) try: cluster = file_study.tree.get(path.split("/"), depth=1) except KeyError: - raise ClusterNotFound(cluster_id) + raise RenewableClusterNotFound(path, cluster_id) return create_renewable_output(study.version, cluster_id, cluster) def update_cluster( @@ -222,7 +254,7 @@ def update_cluster( The updated cluster configuration. Raises: - ClusterNotFound: If the cluster to update is not found. + RenewableClusterNotFound: If the cluster to update is not found. """ study_version = study.version @@ -232,7 +264,7 @@ def update_cluster( try: values = file_study.tree.get(path.split("/"), depth=1) except KeyError: - raise ClusterNotFound(cluster_id) from None + raise RenewableClusterNotFound(path, cluster_id) from None else: old_config = create_renewable_config(study_version, **values) @@ -298,12 +330,12 @@ def duplicate_cluster( The duplicated cluster configuration. Raises: - ClusterAlreadyExists: If a cluster with the new name already exists in the area. + DuplicateRenewableCluster: If a cluster with the new name already exists in the area. """ new_id = transform_name_to_id(new_cluster_name, lower=False) lower_new_id = new_id.lower() if any(lower_new_id == cluster.id.lower() for cluster in self.get_clusters(study, area_id)): - raise ClusterAlreadyExists("Renewable", new_id) + raise DuplicateRenewableCluster(area_id, new_id) # Cluster duplication current_cluster = self.get_cluster(study, area_id, source_id) @@ -327,3 +359,42 @@ def duplicate_cluster( execute_or_add_commands(study, self._get_file_study(study), commands, self.storage_service) return RenewableClusterOutput(**new_config.dict(by_alias=False)) + + def update_renewables_props( + self, + study: Study, + update_renewables_by_areas: t.Mapping[str, t.Mapping[str, RenewableClusterInput]], + ) -> t.Mapping[str, t.Mapping[str, RenewableClusterOutput]]: + old_renewables_by_areas = self.get_all_renewables_props(study) + new_renewables_by_areas = {area_id: dict(clusters) for area_id, clusters in old_renewables_by_areas.items()} + + # Prepare the commands to update the renewable clusters. + commands = [] + for area_id, update_renewables_by_ids in update_renewables_by_areas.items(): + old_renewables_by_ids = old_renewables_by_areas[area_id] + for renewable_id, update_cluster in update_renewables_by_ids.items(): + # Update the renewable cluster properties. + old_cluster = old_renewables_by_ids[renewable_id] + new_cluster = old_cluster.copy(update=update_cluster.dict(by_alias=False, exclude_none=True)) + new_renewables_by_areas[area_id][renewable_id] = new_cluster + + # Convert the DTO to a configuration object and update the configuration file. + properties = create_renewable_config( + study.version, **new_cluster.dict(by_alias=False, exclude_none=True) + ) + path = _CLUSTER_PATH.format(area_id=area_id, cluster_id=renewable_id) + cmd = UpdateConfig( + target=path, + data=json.loads(properties.json(by_alias=True, exclude={"id"})), + command_context=self.storage_service.variant_study_service.command_factory.command_context, + ) + commands.append(cmd) + + file_study = self.storage_service.get_storage(study).get_raw(study) + execute_or_add_commands(study, file_study, commands, self.storage_service) + + return new_renewables_by_areas + + @staticmethod + def get_table_schema() -> JSON: + return RenewableClusterOutput.schema() diff --git a/antarest/study/business/areas/st_storage_management.py b/antarest/study/business/areas/st_storage_management.py index 7109d8c668..373f8c3ea4 100644 --- a/antarest/study/business/areas/st_storage_management.py +++ b/antarest/study/business/areas/st_storage_management.py @@ -1,3 +1,4 @@ +import collections import functools import json import operator @@ -5,45 +6,39 @@ import numpy as np from pydantic import BaseModel, Extra, root_validator, validator +from requests.structures import CaseInsensitiveDict from typing_extensions import Literal from antarest.core.exceptions import ( AreaNotFound, - ClusterAlreadyExists, - DuplicateSTStorageId, - STStorageConfigNotFoundError, - STStorageFieldsNotFoundError, - STStorageMatrixNotFoundError, - STStorageNotFoundError, + DuplicateSTStorage, + STStorageConfigNotFound, + STStorageMatrixNotFound, + STStorageNotFound, ) -from antarest.study.business.utils import AllOptionalMetaclass, camel_case_model, execute_or_add_commands +from antarest.core.model import JSON +from antarest.study.business.all_optional_meta import AllOptionalMetaclass, camel_case_model +from antarest.study.business.utils import execute_or_add_commands from antarest.study.model import Study from antarest.study.storage.rawstudy.model.filesystem.config.model import transform_name_to_id from antarest.study.storage.rawstudy.model.filesystem.config.st_storage import ( - STStorageConfig, + STStorage880Config, + STStorage880Properties, + STStorageConfigType, STStorageGroup, - STStorageProperties, create_st_storage_config, ) from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy +from antarest.study.storage.rawstudy.model.filesystem.folder_node import ChildNotFoundError from antarest.study.storage.storage_service import StudyStorageService from antarest.study.storage.variantstudy.model.command.create_st_storage import CreateSTStorage from antarest.study.storage.variantstudy.model.command.remove_st_storage import RemoveSTStorage from antarest.study.storage.variantstudy.model.command.replace_matrix import ReplaceMatrix from antarest.study.storage.variantstudy.model.command.update_config import UpdateConfig -__all__ = ( - "STStorageManager", - "STStorageCreation", - "STStorageInput", - "STStorageOutput", - "STStorageMatrix", - "STStorageTimeSeries", -) - @camel_case_model -class STStorageInput(STStorageProperties, metaclass=AllOptionalMetaclass, use_none=True): +class STStorageInput(STStorage880Properties, metaclass=AllOptionalMetaclass, use_none=True): """ Model representing the form used to EDIT an existing short-term storage. """ @@ -79,13 +74,13 @@ def validate_name(cls, name: t.Optional[str]) -> str: return name # noinspection PyUnusedLocal - def to_config(self, study_version: t.Union[str, int]) -> STStorageConfig: + def to_config(self, study_version: t.Union[str, int]) -> STStorageConfigType: values = self.dict(by_alias=False, exclude_none=True) - return STStorageConfig(**values) + return create_st_storage_config(study_version=study_version, **values) @camel_case_model -class STStorageOutput(STStorageConfig): +class STStorageOutput(STStorage880Config, metaclass=AllOptionalMetaclass, use_none=True): """ Model representing the form used to display the details of a short-term storage entry. """ @@ -104,12 +99,6 @@ def schema_extra(schema: t.MutableMapping[str, t.Any]) -> None: initial_level_optim=True, ) - @classmethod - def from_config(cls, storage_id: str, config: t.Mapping[str, t.Any]) -> "STStorageOutput": - storage = STStorageConfig(**config, id=storage_id) - values = storage.dict(by_alias=False) - return cls(**values) - # ============= # Time series @@ -227,8 +216,29 @@ def validate_rule_curve( # ============================ -STORAGE_LIST_PATH = "input/st-storage/clusters/{area_id}/list/{storage_id}" -STORAGE_SERIES_PATH = "input/st-storage/series/{area_id}/{storage_id}/{ts_name}" +_STORAGE_LIST_PATH = "input/st-storage/clusters/{area_id}/list/{storage_id}" +_STORAGE_SERIES_PATH = "input/st-storage/series/{area_id}/{storage_id}/{ts_name}" +_ALL_STORAGE_PATH = "input/st-storage/clusters" + + +def _get_values_by_ids(file_study: FileStudy, area_id: str) -> t.Mapping[str, t.Mapping[str, t.Any]]: + path = _STORAGE_LIST_PATH.format(area_id=area_id, storage_id="")[:-1] + try: + return CaseInsensitiveDict(file_study.tree.get(path.split("/"), depth=3)) + except ChildNotFoundError: + raise AreaNotFound(area_id) from None + except KeyError: + raise STStorageConfigNotFound(path, area_id) from None + + +def create_storage_output( + study_version: t.Union[str, int], + cluster_id: str, + config: t.Mapping[str, t.Any], +) -> "STStorageOutput": + obj = create_st_storage_config(study_version=study_version, **config, id=cluster_id) + kwargs = obj.dict(by_alias=False) + return STStorageOutput(**kwargs) class STStorageManager: @@ -264,8 +274,13 @@ def create_storage( The ID of the newly created short-term storage. """ file_study = self._get_file_study(study) + values_by_ids = _get_values_by_ids(file_study, area_id) + storage = form.to_config(study.version) - _check_creation_feasibility(file_study, area_id, storage.id) + values = values_by_ids.get(storage.id) + if values is not None: + raise DuplicateSTStorage(area_id, storage.id) + command = self._make_create_cluster_cmd(area_id, storage) execute_or_add_commands( study, @@ -276,7 +291,7 @@ def create_storage( output = self.get_storage(study, area_id, storage_id=storage.id) return output - def _make_create_cluster_cmd(self, area_id: str, cluster: STStorageConfig) -> CreateSTStorage: + def _make_create_cluster_cmd(self, area_id: str, cluster: STStorageConfigType) -> CreateSTStorage: command = CreateSTStorage( area_id=area_id, parameters=cluster, @@ -301,19 +316,90 @@ def get_storages( """ file_study = self._get_file_study(study) - path = STORAGE_LIST_PATH.format(area_id=area_id, storage_id="")[:-1] + path = _STORAGE_LIST_PATH.format(area_id=area_id, storage_id="")[:-1] try: config = file_study.tree.get(path.split("/"), depth=3) + except ChildNotFoundError: + raise AreaNotFound(area_id) from None except KeyError: - raise STStorageConfigNotFoundError(study.id, area_id) from None + raise STStorageConfigNotFound(path, area_id) from None # Sort STStorageConfig by groups and then by name order_by = operator.attrgetter("group", "name") - all_configs = sorted( - (STStorageConfig(id=storage_id, **options) for storage_id, options in config.items()), - key=order_by, - ) - return tuple(STStorageOutput(**config.dict(by_alias=False)) for config in all_configs) + study_version = int(study.version) + storages = [create_storage_output(study_version, storage_id, options) for storage_id, options in config.items()] + return sorted(storages, key=order_by) + + def get_all_storages_props( + self, + study: Study, + ) -> t.Mapping[str, t.Mapping[str, STStorageOutput]]: + """ + Retrieve all short-term storages from all areas within a study. + + Args: + study: Study from which to retrieve the storages. + + Returns: + A mapping of area IDs to a mapping of storage IDs to storage configurations. + + Raises: + STStorageConfigNotFound: If no storages are found in the specified area. + """ + + file_study = self._get_file_study(study) + path = _ALL_STORAGE_PATH + try: + # may raise KeyError if the path is missing + storages = file_study.tree.get(path.split("/"), depth=5) + # may raise KeyError if "list" is missing + storages = {area_id: cluster_list["list"] for area_id, cluster_list in storages.items()} + except KeyError: + raise STStorageConfigNotFound(path) from None + + study_version = study.version + storages_by_areas: t.MutableMapping[str, t.MutableMapping[str, STStorageOutput]] + storages_by_areas = collections.defaultdict(dict) + for area_id, cluster_obj in storages.items(): + for cluster_id, cluster in cluster_obj.items(): + storages_by_areas[area_id][cluster_id] = create_storage_output(study_version, cluster_id, cluster) + + return storages_by_areas + + def update_storages_props( + self, + study: Study, + update_storages_by_areas: t.Mapping[str, t.Mapping[str, STStorageInput]], + ) -> t.Mapping[str, t.Mapping[str, STStorageOutput]]: + old_storages_by_areas = self.get_all_storages_props(study) + new_storages_by_areas = {area_id: dict(clusters) for area_id, clusters in old_storages_by_areas.items()} + + # Prepare the commands to update the storage clusters. + commands = [] + for area_id, update_storages_by_ids in update_storages_by_areas.items(): + old_storages_by_ids = old_storages_by_areas[area_id] + for storage_id, update_cluster in update_storages_by_ids.items(): + # Update the storage cluster properties. + old_cluster = old_storages_by_ids[storage_id] + new_cluster = old_cluster.copy(update=update_cluster.dict(by_alias=False, exclude_none=True)) + new_storages_by_areas[area_id][storage_id] = new_cluster + + # Convert the DTO to a configuration object and update the configuration file. + properties = create_st_storage_config( + study.version, **new_cluster.dict(by_alias=False, exclude_none=True) + ) + path = _STORAGE_LIST_PATH.format(area_id=area_id, storage_id=storage_id) + cmd = UpdateConfig( + target=path, + data=json.loads(properties.json(by_alias=True, exclude={"id"})), + command_context=self.storage_service.variant_study_service.command_factory.command_context, + ) + commands.append(cmd) + + file_study = self.storage_service.get_storage(study).get_raw(study) + execute_or_add_commands(study, file_study, commands, self.storage_service) + + return new_storages_by_areas def get_storage( self, @@ -334,12 +420,12 @@ def get_storage( """ file_study = self._get_file_study(study) - path = STORAGE_LIST_PATH.format(area_id=area_id, storage_id=storage_id) + path = _STORAGE_LIST_PATH.format(area_id=area_id, storage_id=storage_id) try: config = file_study.tree.get(path.split("/"), depth=1) except KeyError: - raise STStorageFieldsNotFoundError(storage_id) from None - return STStorageOutput.from_config(storage_id, config) + raise STStorageNotFound(path, storage_id) from None + return create_storage_output(int(study.version), storage_id, config) def update_storage( self, @@ -365,15 +451,13 @@ def update_storage( # But sadly, there's no other way to prevent creating wrong commands. file_study = self._get_file_study(study) - _check_update_feasibility(file_study, area_id, storage_id) + values_by_ids = _get_values_by_ids(file_study, area_id) - path = STORAGE_LIST_PATH.format(area_id=area_id, storage_id=storage_id) - try: - values = file_study.tree.get(path.split("/"), depth=1) - except KeyError: - raise STStorageFieldsNotFoundError(storage_id) from None - else: - old_config = create_st_storage_config(study_version, **values) + values = values_by_ids.get(storage_id) + if values is None: + path = _STORAGE_LIST_PATH.format(area_id=area_id, storage_id=storage_id) + raise STStorageNotFound(path, storage_id) + old_config = create_st_storage_config(study_version, **values) # use Python values to synchronize Config and Form values new_values = form.dict(by_alias=False, exclude_none=True) @@ -389,6 +473,7 @@ def update_storage( # create the update config commands with the modified data command_context = self.storage_service.variant_study_service.command_factory.command_context + path = _STORAGE_LIST_PATH.format(area_id=area_id, storage_id=storage_id) commands = [ UpdateConfig(target=f"{path}/{key}", data=value, command_context=command_context) for key, value in data.items() @@ -413,7 +498,12 @@ def delete_storages( storage_ids: IDs list of short-term storages to remove. """ file_study = self._get_file_study(study) - _check_deletion_feasibility(file_study, area_id, storage_ids) + values_by_ids = _get_values_by_ids(file_study, area_id) + + for storage_id in storage_ids: + if storage_id not in values_by_ids: + path = _STORAGE_LIST_PATH.format(area_id=area_id, storage_id=storage_id) + raise STStorageNotFound(path, storage_id) command_context = self.storage_service.variant_study_service.command_factory.command_context for storage_id in storage_ids: @@ -443,12 +533,17 @@ def duplicate_cluster(self, study: Study, area_id: str, source_id: str, new_clus new_id = transform_name_to_id(new_cluster_name) lower_new_id = new_id.lower() if any(lower_new_id == storage.id.lower() for storage in self.get_storages(study, area_id)): - raise ClusterAlreadyExists("Short-term storage", new_id) + raise DuplicateSTStorage(area_id, new_id) # Cluster duplication current_cluster = self.get_storage(study, area_id, source_id) current_cluster.name = new_cluster_name - creation_form = STStorageCreation(**current_cluster.dict(by_alias=False, exclude={"id"})) + fields_to_exclude = {"id"} + # We should remove the field 'enabled' for studies before v8.8 as it didn't exist + if int(study.version) < 880: + fields_to_exclude.add("enabled") + creation_form = STStorageCreation(**current_cluster.dict(by_alias=False, exclude=fields_to_exclude)) + new_config = creation_form.to_config(study.version) create_cluster_cmd = self._make_create_cluster_cmd(area_id, new_config) @@ -457,11 +552,11 @@ def duplicate_cluster(self, study: Study, area_id: str, source_id: str, new_clus # noinspection SpellCheckingInspection ts_names = ["pmax_injection", "pmax_withdrawal", "lower_rule_curve", "upper_rule_curve", "inflows"] source_paths = [ - STORAGE_SERIES_PATH.format(area_id=area_id, storage_id=lower_source_id, ts_name=ts_name) + _STORAGE_SERIES_PATH.format(area_id=area_id, storage_id=lower_source_id, ts_name=ts_name) for ts_name in ts_names ] new_paths = [ - STORAGE_SERIES_PATH.format(area_id=area_id, storage_id=lower_new_id, ts_name=ts_name) + _STORAGE_SERIES_PATH.format(area_id=area_id, storage_id=lower_new_id, ts_name=ts_name) for ts_name in ts_names ] @@ -508,11 +603,11 @@ def _get_matrix_obj( ts_name: STStorageTimeSeries, ) -> t.MutableMapping[str, t.Any]: file_study = self._get_file_study(study) - path = STORAGE_SERIES_PATH.format(area_id=area_id, storage_id=storage_id, ts_name=ts_name) + path = _STORAGE_SERIES_PATH.format(area_id=area_id, storage_id=storage_id, ts_name=ts_name) try: matrix = file_study.tree.get(path.split("/"), depth=1) except KeyError: - raise STStorageMatrixNotFoundError(study.id, area_id, storage_id, ts_name) from None + raise STStorageMatrixNotFound(path) from None return matrix def update_matrix( @@ -545,7 +640,7 @@ def _save_matrix_obj( ) -> None: file_study = self._get_file_study(study) command_context = self.storage_service.variant_study_service.command_factory.command_context - path = STORAGE_SERIES_PATH.format(area_id=area_id, storage_id=storage_id, ts_name=ts_name) + path = _STORAGE_SERIES_PATH.format(area_id=area_id, storage_id=storage_id, ts_name=ts_name) command = ReplaceMatrix(target=path, matrix=matrix_data, command_context=command_context) execute_or_add_commands(study, file_study, [command], self.storage_service) @@ -593,30 +688,6 @@ def validate_matrices( # Validation successful return True - -def _get_existing_storage_ids(file_study: FileStudy, area_id: str) -> t.Set[str]: - try: - area = file_study.config.areas[area_id] - except KeyError: - raise AreaNotFound(area_id) from None - else: - return {s.id for s in area.st_storages} - - -def _check_deletion_feasibility(file_study: FileStudy, area_id: str, storage_ids: t.Sequence[str]) -> None: - existing_ids = _get_existing_storage_ids(file_study, area_id) - for storage_id in storage_ids: - if storage_id not in existing_ids: - raise STStorageNotFoundError(file_study.config.study_id, area_id, storage_id) - - -def _check_update_feasibility(file_study: FileStudy, area_id: str, storage_id: str) -> None: - existing_ids = _get_existing_storage_ids(file_study, area_id) - if storage_id not in existing_ids: - raise STStorageNotFoundError(file_study.config.study_id, area_id, storage_id) - - -def _check_creation_feasibility(file_study: FileStudy, area_id: str, storage_id: str) -> None: - existing_ids = _get_existing_storage_ids(file_study, area_id) - if storage_id in existing_ids: - raise DuplicateSTStorageId(file_study.config.study_id, area_id, storage_id) + @staticmethod + def get_table_schema() -> JSON: + return STStorageOutput.schema() diff --git a/antarest/study/business/areas/thermal_management.py b/antarest/study/business/areas/thermal_management.py index f44ad7ba10..205965eb54 100644 --- a/antarest/study/business/areas/thermal_management.py +++ b/antarest/study/business/areas/thermal_management.py @@ -1,15 +1,25 @@ +import collections import json import typing as t +from pathlib import Path from pydantic import validator -from antarest.core.exceptions import ClusterAlreadyExists, ClusterConfigNotFound, ClusterNotFound -from antarest.study.business.utils import AllOptionalMetaclass, camel_case_model, execute_or_add_commands +from antarest.core.exceptions import ( + DuplicateThermalCluster, + MatrixWidthMismatchError, + ThermalClusterConfigNotFound, + ThermalClusterNotFound, + WrongMatrixHeightError, +) +from antarest.core.model import JSON +from antarest.study.business.all_optional_meta import AllOptionalMetaclass, camel_case_model +from antarest.study.business.utils import execute_or_add_commands from antarest.study.model import Study from antarest.study.storage.rawstudy.model.filesystem.config.model import transform_name_to_id from antarest.study.storage.rawstudy.model.filesystem.config.thermal import ( - Thermal860Config, - Thermal860Properties, + Thermal870Config, + Thermal870Properties, ThermalConfigType, create_thermal_config, ) @@ -29,10 +39,11 @@ _CLUSTER_PATH = "input/thermal/clusters/{area_id}/list/{cluster_id}" _CLUSTERS_PATH = "input/thermal/clusters/{area_id}/list" +_ALL_CLUSTERS_PATH = "input/thermal/clusters" @camel_case_model -class ThermalClusterInput(Thermal860Properties, metaclass=AllOptionalMetaclass, use_none=True): +class ThermalClusterInput(Thermal870Properties, metaclass=AllOptionalMetaclass, use_none=True): """ Model representing the data structure required to edit an existing thermal cluster within a study. """ @@ -72,7 +83,7 @@ def to_config(self, study_version: t.Union[str, int]) -> ThermalConfigType: @camel_case_model -class ThermalClusterOutput(Thermal860Config, metaclass=AllOptionalMetaclass, use_none=True): +class ThermalClusterOutput(Thermal870Config, metaclass=AllOptionalMetaclass, use_none=True): """ Model representing the output data structure to display the details of a thermal cluster within a study. """ @@ -138,7 +149,7 @@ def get_cluster(self, study: Study, area_id: str, cluster_id: str) -> ThermalClu The cluster with the specified ID. Raises: - ClusterNotFound: If the specified cluster does not exist. + ThermalClusterNotFound: If the specified cluster does not exist. """ file_study = self._get_file_study(study) @@ -146,7 +157,7 @@ def get_cluster(self, study: Study, area_id: str, cluster_id: str) -> ThermalClu try: cluster = file_study.tree.get(path.split("/"), depth=1) except KeyError: - raise ClusterNotFound(cluster_id) + raise ThermalClusterNotFound(path, cluster_id) from None study_version = study.version return create_thermal_output(study_version, cluster_id, cluster) @@ -166,7 +177,7 @@ def get_clusters( A list of thermal clusters within the specified area. Raises: - ClusterConfigNotFound: If no clusters are found in the specified area. + ThermalClusterConfigNotFound: If no clusters are found in the specified area. """ file_study = self._get_file_study(study) @@ -174,10 +185,83 @@ def get_clusters( try: clusters = file_study.tree.get(path.split("/"), depth=3) except KeyError: - raise ClusterConfigNotFound(area_id) + raise ThermalClusterConfigNotFound(path, area_id) from None study_version = study.version return [create_thermal_output(study_version, cluster_id, cluster) for cluster_id, cluster in clusters.items()] + def get_all_thermals_props( + self, + study: Study, + ) -> t.Mapping[str, t.Mapping[str, ThermalClusterOutput]]: + """ + Retrieve all thermal clusters from all areas within a study. + + Args: + study: Study from which to retrieve the clusters. + + Returns: + A mapping of area IDs to a mapping of cluster IDs to thermal cluster configurations. + + Raises: + ThermalClusterConfigNotFound: If no clusters are found in the specified area. + """ + + file_study = self._get_file_study(study) + path = _ALL_CLUSTERS_PATH + try: + # may raise KeyError if the path is missing + clusters = file_study.tree.get(path.split("/"), depth=5) + # may raise KeyError if "list" is missing + clusters = {area_id: cluster_list["list"] for area_id, cluster_list in clusters.items()} + except KeyError: + raise ThermalClusterConfigNotFound(path) from None + + study_version = study.version + thermals_by_areas: t.MutableMapping[str, t.MutableMapping[str, ThermalClusterOutput]] + thermals_by_areas = collections.defaultdict(dict) + for area_id, cluster_obj in clusters.items(): + for cluster_id, cluster in cluster_obj.items(): + thermals_by_areas[area_id][cluster_id] = create_thermal_output(study_version, cluster_id, cluster) + + return thermals_by_areas + + def update_thermals_props( + self, + study: Study, + update_thermals_by_areas: t.Mapping[str, t.Mapping[str, ThermalClusterInput]], + ) -> t.Mapping[str, t.Mapping[str, ThermalClusterOutput]]: + old_thermals_by_areas = self.get_all_thermals_props(study) + new_thermals_by_areas = {area_id: dict(clusters) for area_id, clusters in old_thermals_by_areas.items()} + + # Prepare the commands to update the thermal clusters. + commands = [] + for area_id, update_thermals_by_ids in update_thermals_by_areas.items(): + old_thermals_by_ids = old_thermals_by_areas[area_id] + for thermal_id, update_cluster in update_thermals_by_ids.items(): + # Update the thermal cluster properties. + old_cluster = old_thermals_by_ids[thermal_id] + new_cluster = old_cluster.copy(update=update_cluster.dict(by_alias=False, exclude_none=True)) + new_thermals_by_areas[area_id][thermal_id] = new_cluster + + # Convert the DTO to a configuration object and update the configuration file. + properties = create_thermal_config(study.version, **new_cluster.dict(by_alias=False, exclude_none=True)) + path = _CLUSTER_PATH.format(area_id=area_id, cluster_id=thermal_id) + cmd = UpdateConfig( + target=path, + data=json.loads(properties.json(by_alias=True, exclude={"id"})), + command_context=self.storage_service.variant_study_service.command_factory.command_context, + ) + commands.append(cmd) + + file_study = self.storage_service.get_storage(study).get_raw(study) + execute_or_add_commands(study, file_study, commands, self.storage_service) + + return new_thermals_by_areas + + @staticmethod + def get_table_schema() -> JSON: + return ThermalClusterOutput.schema() + def create_cluster(self, study: Study, area_id: str, cluster_data: ThermalClusterCreation) -> ThermalClusterOutput: """ Create a new cluster. @@ -235,7 +319,7 @@ def update_cluster( The updated cluster. Raises: - ClusterNotFound: If the provided `cluster_id` does not match the ID of the cluster + ThermalClusterNotFound: If the provided `cluster_id` does not match the ID of the cluster in the provided cluster_data. """ @@ -245,7 +329,7 @@ def update_cluster( try: values = file_study.tree.get(path.split("/"), depth=1) except KeyError: - raise ClusterNotFound(cluster_id) from None + raise ThermalClusterNotFound(path, cluster_id) from None else: old_config = create_thermal_config(study_version, **values) @@ -317,7 +401,7 @@ def duplicate_cluster( new_id = transform_name_to_id(new_cluster_name, lower=False) lower_new_id = new_id.lower() if any(lower_new_id == cluster.id.lower() for cluster in self.get_clusters(study, area_id)): - raise ClusterAlreadyExists("Thermal", new_id) + raise DuplicateThermalCluster(area_id, new_id) # Cluster duplication source_cluster = self.get_cluster(study, area_id, source_id) @@ -338,6 +422,11 @@ def duplicate_cluster( f"input/thermal/prepro/{area_id}/{lower_new_id}/modulation", f"input/thermal/prepro/{area_id}/{lower_new_id}/data", ] + if int(study.version) >= 870: + source_paths.append(f"input/thermal/series/{area_id}/{lower_source_id}/CO2Cost") + source_paths.append(f"input/thermal/series/{area_id}/{lower_source_id}/fuelCost") + new_paths.append(f"input/thermal/series/{area_id}/{lower_new_id}/CO2Cost") + new_paths.append(f"input/thermal/series/{area_id}/{lower_new_id}/fuelCost") # Prepare and execute commands commands: t.List[t.Union[CreateCluster, ReplaceMatrix]] = [create_cluster_cmd] @@ -351,3 +440,38 @@ def duplicate_cluster( execute_or_add_commands(study, self._get_file_study(study), commands, self.storage_service) return ThermalClusterOutput(**new_config.dict(by_alias=False)) + + def validate_series(self, study: Study, area_id: str, cluster_id: str) -> bool: + lower_cluster_id = cluster_id.lower() + thermal_cluster_path = Path(f"input/thermal/series/{area_id}/{lower_cluster_id}") + series_path = [thermal_cluster_path / "series"] + if int(study.version) >= 870: + series_path.append(thermal_cluster_path / "CO2Cost") + series_path.append(thermal_cluster_path / "fuelCost") + + ts_widths: t.MutableMapping[int, t.MutableSequence[str]] = {} + for ts_path in series_path: + matrix = self.storage_service.get_storage(study).get(study, ts_path.as_posix()) + matrix_data = matrix["data"] + matrix_height = len(matrix_data) + # We ignore empty matrices as there are default matrices for the simulator. + if matrix_data != [[]] and matrix_height != 8760: + raise WrongMatrixHeightError( + f"The matrix {ts_path.name} should have 8760 rows, currently: {matrix_height}" + ) + matrix_width = len(matrix_data[0]) + if matrix_width > 1: + ts_widths.setdefault(matrix_width, []).append(ts_path.name) + + if len(ts_widths) > 1: + messages = [] + for width, name_list in ts_widths.items(): + names = ", ".join([f"'{name}'" for name in name_list]) + message = { + 1: f"matrix {names} has {width} columns", + 2: f"matrices {names} have {width} columns", + }[min(2, len(name_list))] + messages.append(message) + raise MatrixWidthMismatchError("Mismatch widths: " + "; ".join(messages)) + + return True diff --git a/antarest/study/business/binding_constraint_management.py b/antarest/study/business/binding_constraint_management.py index 55112da1da..28881ef874 100644 --- a/antarest/study/business/binding_constraint_management.py +++ b/antarest/study/business/binding_constraint_management.py @@ -1,35 +1,65 @@ -from typing import Any, Dict, List, Optional, Union +import collections +import itertools +import json +import logging +import typing as t -from pydantic import BaseModel, validator +import numpy as np +from pydantic import BaseModel, Field, root_validator, validator +from requests.utils import CaseInsensitiveDict from antarest.core.exceptions import ( - BindingConstraintNotFoundError, - ConstraintAlreadyExistError, - ConstraintIdNotFoundError, + BindingConstraintNotFound, + ConstraintTermNotFound, DuplicateConstraintName, + DuplicateConstraintTerm, InvalidConstraintName, - MissingDataError, - NoConstraintError, + InvalidConstraintTerm, + InvalidFieldForVersionError, + MatrixWidthMismatchError, + WrongMatrixHeightError, ) -from antarest.matrixstore.model import MatrixData +from antarest.core.model import JSON +from antarest.core.utils.string import to_camel_case +from antarest.study.business.all_optional_meta import camel_case_model from antarest.study.business.utils import execute_or_add_commands from antarest.study.model import Study -from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import BindingConstraintFrequency +from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import ( + BindingConstraintFrequency, + BindingConstraintOperator, +) from antarest.study.storage.rawstudy.model.filesystem.config.model import transform_name_to_id +from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy from antarest.study.storage.storage_service import StudyStorageService -from antarest.study.storage.variantstudy.business.matrix_constants.binding_constraint.series import ( - default_bc_hourly, - default_bc_weekly_daily, +from antarest.study.storage.variantstudy.business.matrix_constants.binding_constraint.series_after_v87 import ( + default_bc_hourly as default_bc_hourly_87, +) +from antarest.study.storage.variantstudy.business.matrix_constants.binding_constraint.series_after_v87 import ( + default_bc_weekly_daily as default_bc_weekly_daily_87, +) +from antarest.study.storage.variantstudy.business.matrix_constants.binding_constraint.series_before_v87 import ( + default_bc_hourly as default_bc_hourly_86, +) +from antarest.study.storage.variantstudy.business.matrix_constants.binding_constraint.series_before_v87 import ( + default_bc_weekly_daily as default_bc_weekly_daily_86, ) -from antarest.study.storage.variantstudy.model.command.common import BindingConstraintOperator from antarest.study.storage.variantstudy.model.command.create_binding_constraint import ( - BindingConstraintProperties, + DEFAULT_GROUP, + EXPECTED_MATRIX_SHAPES, + TERM_MATRICES, + BindingConstraintMatrices, + BindingConstraintPropertiesBase, CreateBindingConstraint, + OptionalProperties, ) +from antarest.study.storage.variantstudy.model.command.remove_binding_constraint import RemoveBindingConstraint from antarest.study.storage.variantstudy.model.command.update_binding_constraint import UpdateBindingConstraint +from antarest.study.storage.variantstudy.model.dbmodel import VariantStudy + +logger = logging.getLogger(__name__) -class AreaLinkDTO(BaseModel): +class LinkTerm(BaseModel): """ DTO for a constraint term on a link between two areas. @@ -48,7 +78,7 @@ def generate_id(self) -> str: return "%".join(ids) -class AreaClusterDTO(BaseModel): +class ClusterTerm(BaseModel): """ DTO for a constraint term on a cluster in an area. @@ -67,7 +97,7 @@ def generate_id(self) -> str: return ".".join(ids) -class ConstraintTermDTO(BaseModel): +class ConstraintTerm(BaseModel): """ DTO for a constraint term. @@ -78,13 +108,13 @@ class ConstraintTermDTO(BaseModel): data: the constraint term data (link or cluster), if any. """ - id: Optional[str] - weight: Optional[float] - offset: Optional[float] - data: Optional[Union[AreaLinkDTO, AreaClusterDTO]] + id: t.Optional[str] + weight: t.Optional[float] + offset: t.Optional[int] + data: t.Optional[t.Union[LinkTerm, ClusterTerm]] @validator("id") - def id_to_lower(cls, v: Optional[str]) -> Optional[str]: + def id_to_lower(cls, v: t.Optional[str]) -> t.Optional[str]: """Ensure the ID is lower case.""" if v is None: return None @@ -97,26 +127,269 @@ def generate_id(self) -> str: return self.data.generate_id() -class UpdateBindingConstProps(BaseModel): - key: str - value: Any +class ConstraintFilters(BaseModel, frozen=True, extra="forbid"): + """ + Binding Constraint Filters gathering the main filtering parameters. + Attributes: + bc_id: binding constraint ID (exact match) + enabled: enabled status + operator: operator + comments: comments (word match, case-insensitive) + group: on group name (exact match, case-insensitive) + time_step: time step + area_name: area name (word match, case-insensitive) + cluster_name: cluster name (word match, case-insensitive) + link_id: link ID ('area1%area2') in at least one term. + cluster_id: cluster ID ('area.cluster') in at least one term. + """ -class BindingConstraintPropertiesWithName(BindingConstraintProperties): + bc_id: str = "" + enabled: t.Optional[bool] = None + operator: t.Optional[BindingConstraintOperator] = None + comments: str = "" + group: str = "" + time_step: t.Optional[BindingConstraintFrequency] = None + area_name: str = "" + cluster_name: str = "" + link_id: str = "" + cluster_id: str = "" + + def match_filters(self, constraint: "ConstraintOutput") -> bool: + """ + Check if the constraint matches the filters. + + Args: + constraint: the constraint to check + + Returns: + True if the constraint matches the filters, False otherwise + """ + if self.bc_id and self.bc_id != constraint.id: + # The `bc_id` filter is a case-sensitive exact match. + return False + if self.enabled is not None and self.enabled != constraint.enabled: + return False + if self.operator is not None and self.operator != constraint.operator: + return False + if self.comments: + # The `comments` filter is a case-insensitive substring match. + comments = constraint.comments or "" + if self.comments.upper() not in comments.upper(): + return False + if self.group: + # The `group` filter is a case-insensitive exact match. + group = getattr(constraint, "group", DEFAULT_GROUP) + if self.group.upper() != group.upper(): + return False + if self.time_step is not None and self.time_step != constraint.time_step: + return False + + terms = constraint.terms or [] + + if self.area_name: + # The `area_name` filter is a case-insensitive substring match. + area_name_upper = self.area_name.upper() + for data in (term.data for term in terms if term.data): + # fmt: off + if ( + isinstance(data, LinkTerm) + and (area_name_upper in data.area1.upper() or area_name_upper in data.area2.upper()) + ) or ( + isinstance(data, ClusterTerm) + and area_name_upper in data.area.upper() + ): + break + # fmt: on + else: + return False + + if self.cluster_name: + # The `cluster_name` filter is a case-insensitive substring match. + cluster_name_upper = self.cluster_name.upper() + for data in (term.data for term in terms if term.data): + if isinstance(data, ClusterTerm) and cluster_name_upper in data.cluster.upper(): + break + else: + return False + + if self.link_id: + # The `link_id` filter is a case-insensitive exact match. + all_link_ids = [term.data.generate_id() for term in terms if isinstance(term.data, LinkTerm)] + if self.link_id.lower() not in all_link_ids: + return False + + if self.cluster_id: + # The `cluster_id` filter is a case-insensitive exact match. + all_cluster_ids = [term.data.generate_id() for term in terms if isinstance(term.data, ClusterTerm)] + if self.cluster_id.lower() not in all_cluster_ids: + return False + + return True + + +@camel_case_model +class ConstraintInput870(OptionalProperties): + pass + + +@camel_case_model +class ConstraintInput(BindingConstraintMatrices, ConstraintInput870): + terms: t.MutableSequence[ConstraintTerm] = Field( + default_factory=lambda: [], + ) + + +@camel_case_model +class ConstraintCreation(ConstraintInput): name: str + @root_validator(pre=True) + def check_matrices_dimensions(cls, values: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]: + for _key in ["time_step"] + TERM_MATRICES: + _camel = to_camel_case(_key) + values[_key] = values.pop(_camel, values.get(_key)) + + # The dimensions of the matrices depend on the frequency and the version of the study. + if values.get("time_step") is None: + return values + _time_step = BindingConstraintFrequency(values["time_step"]) + + # Matrix shapes for binding constraints are different from usual shapes, + # because we need to take leap years into account, which contains 366 days and 8784 hours. + # Also, we use the same matrices for "weekly" and "daily" frequencies, + # because the solver calculates the weekly matrix from the daily matrix. + # See https://github.com/AntaresSimulatorTeam/AntaREST/issues/1843 + expected_rows = EXPECTED_MATRIX_SHAPES[_time_step][0] + + # Collect the matrix shapes + matrix_shapes = {} + for _field_name in ["values"] + TERM_MATRICES: + if _matrix := values.get(_field_name): + _array = np.array(_matrix) + # We only store the shape if the array is not empty + if _array.size != 0: + matrix_shapes[_field_name] = _array.shape + + # We don't know the exact version of the study here, but we can rely on the matrix field names. + if not matrix_shapes: + return values + elif "values" in matrix_shapes: + expected_cols = 3 + else: + # pick the first matrix column as the expected column + expected_cols = next(iter(matrix_shapes.values()))[1] + + if all(shape == (expected_rows, expected_cols) for shape in matrix_shapes.values()): + return values -class BindingConstraintDTO(BaseModel): + # Prepare a clear error message + _field_names = ", ".join(f"'{n}'" for n in matrix_shapes) + if len(matrix_shapes) == 1: + err_msg = f"Matrix {_field_names} must have the shape ({expected_rows}, {expected_cols})" + else: + _shapes = list({(expected_rows, s[1]) for s in matrix_shapes.values()}) + _shapes_msg = ", ".join(f"{s}" for s in _shapes[:-1]) + " or " + f"{_shapes[-1]}" + err_msg = f"Matrices {_field_names} must have the same shape: {_shapes_msg}" + + raise ValueError(err_msg) + + +@camel_case_model +class ConstraintOutputBase(BindingConstraintPropertiesBase): id: str name: str - enabled: bool = True - time_step: BindingConstraintFrequency - operator: BindingConstraintOperator - values: Optional[Union[List[List[MatrixData]], str]] = None - comments: Optional[str] = None - filter_year_by_year: Optional[str] = None - filter_synthesis: Optional[str] = None - constraints: Optional[List[ConstraintTermDTO]] + terms: t.MutableSequence[ConstraintTerm] = Field(default_factory=lambda: []) + + +@camel_case_model +class ConstraintOutput830(ConstraintOutputBase): + filter_year_by_year: str = "" + filter_synthesis: str = "" + + +@camel_case_model +class ConstraintOutput870(ConstraintOutput830): + group: str = DEFAULT_GROUP + + +# WARNING: Do not change the order of the following line, it is used to determine +# the type of the output constraint in the FastAPI endpoint. +ConstraintOutput = t.Union[ConstraintOutputBase, ConstraintOutput830, ConstraintOutput870] + + +def _get_references_by_widths( + file_study: FileStudy, bcs: t.Sequence[ConstraintOutput] +) -> t.Mapping[int, t.Sequence[t.Tuple[str, str]]]: + """ + Iterates over each BC and its associated matrices. + For each matrix, it checks its width according to the expected matrix shapes. + It then groups the binding constraints by these widths. + + Notes: + The height of the matrices may vary depending on the time step, + but the width should be consistent within a group of binding constraints. + """ + if int(file_study.config.version) < 870: + matrix_id_fmts = {"{bc_id}"} + else: + matrix_id_fmts = {"{bc_id}_eq", "{bc_id}_lt", "{bc_id}_gt"} + + references_by_width: t.Dict[int, t.List[t.Tuple[str, str]]] = {} + _total = len(bcs) * len(matrix_id_fmts) + for _index, (bc, fmt) in enumerate(itertools.product(bcs, matrix_id_fmts), 1): + bc_id = bc.id + matrix_id = fmt.format(bc_id=bc.id) + logger.info(f"⏲ Validating BC '{bc_id}': {matrix_id=} [{_index}/{_total}]") + obj = file_study.tree.get(url=["input", "bindingconstraints", matrix_id]) + matrix = np.array(obj["data"], dtype=float) + # We ignore empty matrices as there are default matrices for the simulator. + if not matrix.size: + continue + + matrix_height = matrix.shape[0] + expected_height = EXPECTED_MATRIX_SHAPES[bc.time_step][0] + if matrix_height != expected_height: + raise WrongMatrixHeightError( + f"The binding constraint '{bc.name}' should have {expected_height} rows, currently: {matrix_height}" + ) + matrix_width = matrix.shape[1] + if matrix_width > 1: + references_by_width.setdefault(matrix_width, []).append((bc_id, matrix_id)) + + return references_by_width + + +def _validate_binding_constraints(file_study: FileStudy, bcs: t.Sequence[ConstraintOutput]) -> bool: + """ + Validates the binding constraints within a group. + """ + references_by_widths = _get_references_by_widths(file_study, bcs) + + if len(references_by_widths) > 1: + most_common = collections.Counter(references_by_widths.keys()).most_common() + invalid_constraints: t.Dict[str, str] = {} + + for width, _ in most_common[1:]: + references = references_by_widths[width] + for bc_id, matrix_id in references: + existing_key = invalid_constraints.get(bc_id, "") + if existing_key: + existing_key += ", " + existing_key += f"'{matrix_id}' has {width} columns" + invalid_constraints[bc_id] = existing_key + + expected_width = most_common[0][0] + raise MatrixWidthMismatchError( + f"Mismatch widths: the most common width in the group is {expected_width}" + f" but we have: {invalid_constraints!r}" + ) + + return True + + +# noinspection SpellCheckingInspection +_ALL_BINDING_CONSTRAINTS_PATH = "input/bindingconstraints/bindingconstraints" class BindingConstraintManager: @@ -127,278 +400,532 @@ def __init__( self.storage_service = storage_service @staticmethod - def parse_constraint(key: str, value: str, char: str, new_config: BindingConstraintDTO) -> bool: - split = key.split(char) - if len(split) == 2: - value1 = split[0] - value2 = split[1] - weight = 0.0 - offset = None - try: - weight = float(value) - except ValueError: - weight_and_offset = value.split("%") - if len(weight_and_offset) == 2: - weight = float(weight_and_offset[0]) - offset = float(weight_and_offset[1]) - if new_config.constraints is None: - new_config.constraints = [] - new_config.constraints.append( - ConstraintTermDTO( - id=key, - weight=weight, - offset=offset if offset is not None else None, - data=AreaLinkDTO( - area1=value1, - area2=value2, + def parse_and_add_terms(key: str, value: t.Any, adapted_constraint: ConstraintOutput) -> None: + """Parse a single term from the constraint dictionary and add it to the adapted_constraint model.""" + if "%" in key or "." in key: + separator = "%" if "%" in key else "." + term_data = key.split(separator) + if isinstance(value, (float, int)): + weight, offset = (float(value), None) + else: + _parts = value.partition("%") + weight = float(_parts[0]) + offset = int(_parts[2]) if _parts[2] else None + + if separator == "%": + # Link term + adapted_constraint.terms.append( + ConstraintTerm( + id=key, + weight=weight, + offset=offset, + data={ + "area1": term_data[0], + "area2": term_data[1], + }, + ) + ) + # Cluster term + else: + adapted_constraint.terms.append( + ConstraintTerm( + id=key, weight=weight, offset=offset, data={"area": term_data[0], "cluster": term_data[1]} ) - if char == "%" - else AreaClusterDTO( - area=value1, - cluster=value2, - ), ) - ) - return True - return False @staticmethod - def process_constraint( - constraint_value: Dict[str, Any], - ) -> BindingConstraintDTO: - new_config: BindingConstraintDTO = BindingConstraintDTO( - id=constraint_value["id"], - name=constraint_value["name"], - enabled=constraint_value["enabled"], - time_step=constraint_value["type"], - operator=constraint_value["operator"], - comments=constraint_value.get("comments", None), - filter_year_by_year=constraint_value.get("filter-year-by-year", ""), - filter_synthesis=constraint_value.get("filter-synthesis", ""), - constraints=None, - ) - for key, value in constraint_value.items(): - if BindingConstraintManager.parse_constraint(key, value, "%", new_config): - continue - if BindingConstraintManager.parse_constraint(key, value, ".", new_config): - continue - return new_config + def constraint_model_adapter(constraint: t.Mapping[str, t.Any], version: int) -> ConstraintOutput: + """ + Adapts a binding constraint configuration to the appropriate model version. + + Args: + constraint: A dictionary or model representing the constraint to be adapted. + This can either be a dictionary coming from client input or an existing + model that needs reformatting. + version: An integer indicating the target version of the study configuration. This is used to + determine which model class to instantiate and which default values to apply. + + Returns: + A new instance of either `ConstraintOutputBase`, `ConstraintOutput830`, or `ConstraintOutput870`, + populated with the adapted values from the input constraint, and conforming to the + structure expected by the specified version. + + Note: + This method is crucial for ensuring backward compatibility and future-proofing the application + as it evolves. It allows client-side data to be accurately represented within the config and + ensures data integrity when storing or retrieving constraint configurations from the database. + """ + + constraint_output = { + "id": constraint["id"], + "name": constraint["name"], + "enabled": constraint.get("enabled", True), + "time_step": constraint.get("type", BindingConstraintFrequency.HOURLY), + "operator": constraint.get("operator", BindingConstraintOperator.EQUAL), + "comments": constraint.get("comments", ""), + "terms": constraint.get("terms", []), + } + + if version >= 830: + _filter_year_by_year = constraint.get("filter_year_by_year") or constraint.get("filter-year-by-year", "") + _filter_synthesis = constraint.get("filter_synthesis") or constraint.get("filter-synthesis", "") + constraint_output["filter_year_by_year"] = _filter_year_by_year + constraint_output["filter_synthesis"] = _filter_synthesis + if version >= 870: + constraint_output["group"] = constraint.get("group", DEFAULT_GROUP) + + # Choose the right model according to the version + adapted_constraint: ConstraintOutput + if version >= 870: + adapted_constraint = ConstraintOutput870(**constraint_output) + elif version >= 830: + adapted_constraint = ConstraintOutput830(**constraint_output) + else: + adapted_constraint = ConstraintOutputBase(**constraint_output) + + # If 'terms' were not directly provided in the input, parse and add terms dynamically + if not constraint.get("terms"): + for key, value in constraint.items(): + if key not in constraint_output: # Avoid re-processing keys already included + BindingConstraintManager.parse_and_add_terms(key, value, adapted_constraint) + + return adapted_constraint @staticmethod - def constraints_to_coeffs( - constraint: BindingConstraintDTO, - ) -> Dict[str, List[float]]: - coeffs: Dict[str, List[float]] = {} - if constraint.constraints is not None: - for term in constraint.constraints: - if term.id is not None and term.weight is not None: + def terms_to_coeffs(terms: t.Sequence[ConstraintTerm]) -> t.Dict[str, t.List[float]]: + """ + Converts a sequence of terms into a dictionary mapping each term's ID to its coefficients, + including the weight and, optionally, the offset. + + :param terms: A sequence of terms to be converted. + :return: A dictionary of term IDs mapped to a list of their coefficients. + """ + coeffs = {} + if terms is not None: + for term in terms: + if term.id and term.weight is not None: coeffs[term.id] = [term.weight] - if term.offset is not None: + if term.offset: coeffs[term.id].append(term.offset) + return coeffs + + def get_binding_constraint(self, study: Study, bc_id: str) -> ConstraintOutput: + """ + Retrieves a binding constraint by its ID within a given study. + + Args: + study: The study from which to retrieve the constraint. + bc_id: The ID of the binding constraint to retrieve. + + Returns: + A ConstraintOutput object representing the binding constraint with the specified ID. + + Raises: + BindingConstraintNotFound: If no binding constraint with the specified ID is found. + """ + storage_service = self.storage_service.get_storage(study) + file_study = storage_service.get_raw(study) + config = file_study.tree.get(["input", "bindingconstraints", "bindingconstraints"]) + + constraints_by_id: t.Dict[str, ConstraintOutput] = CaseInsensitiveDict() # type: ignore + + for constraint in config.values(): + constraint_config = self.constraint_model_adapter(constraint, int(study.version)) + constraints_by_id[constraint_config.id] = constraint_config + + if bc_id not in constraints_by_id: + raise BindingConstraintNotFound(f"Binding constraint '{bc_id}' not found") + + return constraints_by_id[bc_id] + + def get_binding_constraints( + self, study: Study, filters: ConstraintFilters = ConstraintFilters() + ) -> t.Sequence[ConstraintOutput]: + """ + Retrieves all binding constraints within a given study, optionally filtered by specific criteria. - return coeffs + Args: + study: The study from which to retrieve the constraints. + filters: The filters to apply when retrieving the constraints. - def get_binding_constraint( - self, study: Study, constraint_id: Optional[str] - ) -> Union[BindingConstraintDTO, List[BindingConstraintDTO], None]: + Returns: + A list of ConstraintOutput objects representing the binding constraints that match the specified filters. + """ storage_service = self.storage_service.get_storage(study) file_study = storage_service.get_raw(study) config = file_study.tree.get(["input", "bindingconstraints", "bindingconstraints"]) - config_values = list(config.values()) - if constraint_id: + outputs = [self.constraint_model_adapter(c, int(study.version)) for c in config.values()] + filtered_constraints = list(filter(lambda c: filters.match_filters(c), outputs)) + return filtered_constraints + + def get_grouped_constraints(self, study: Study) -> t.Mapping[str, t.Sequence[ConstraintOutput]]: + """ + Retrieves and groups all binding constraints by their group names within a given study. + + This method organizes binding constraints into a dictionary where each key corresponds to a group name, + and the value is a list of ConstraintOutput objects associated with that group. + + Args: + study: the study + + Returns: + A dictionary mapping group names to lists of binding constraints associated with each group. + + Notes: + The grouping considers the exact group name, implying case sensitivity. If case-insensitive grouping + is required, normalization of group names to a uniform case (e.g., all lower or upper) should be performed. + """ + storage_service = self.storage_service.get_storage(study) + file_study = storage_service.get_raw(study) + config = file_study.tree.get(["input", "bindingconstraints", "bindingconstraints"]) + grouped_constraints = CaseInsensitiveDict() # type: ignore + + for constraint in config.values(): + constraint_config = self.constraint_model_adapter(constraint, int(study.version)) + constraint_group = getattr(constraint_config, "group", DEFAULT_GROUP) + grouped_constraints.setdefault(constraint_group, []).append(constraint_config) + + return grouped_constraints + + def get_constraints_by_group(self, study: Study, group_name: str) -> t.Sequence[ConstraintOutput]: + """ + Retrieve all binding constraints belonging to a specified group within a study. + + Args: + study: The study from which to retrieve the constraints. + group_name: The name of the group (case-insensitive). + + Returns: + A list of ConstraintOutput objects that belong to the specified group. + + Raises: + BindingConstraintNotFound: If the specified group name is not found among the constraint groups. + """ + grouped_constraints = self.get_grouped_constraints(study) + + if group_name not in grouped_constraints: + raise BindingConstraintNotFound(f"Group '{group_name}' not found") + + return grouped_constraints[group_name] + + def validate_constraint_group(self, study: Study, group_name: str) -> bool: + """ + Validates if the specified group name exists within the study's binding constraints + and checks the validity of the constraints within that group. + + This method performs a case-insensitive search to match the specified group name against + existing groups of binding constraints. It ensures that the group exists and then + validates the constraints within that found group. + + Args: + study: The study object containing binding constraints. + group_name: The name of the group (case-insensitive). + + Returns: + True if the group exists and the constraints within the group are valid; False otherwise. + + Raises: + BindingConstraintNotFound: If no matching group name is found in a case-insensitive manner. + """ + storage_service = self.storage_service.get_storage(study) + file_study = storage_service.get_raw(study) + grouped_constraints = self.get_grouped_constraints(study) + + if group_name not in grouped_constraints: + raise BindingConstraintNotFound(f"Group '{group_name}' not found") + + constraints = grouped_constraints[group_name] + return _validate_binding_constraints(file_study, constraints) + + def validate_constraint_groups(self, study: Study) -> bool: + """ + Validates all groups of binding constraints within the given study. + + This method checks each group of binding constraints for validity based on specific criteria + (e.g., coherence between matrices lengths). If any group fails the validation, an aggregated + error detailing all incoherence is raised. + + Args: + study: The study object containing binding constraints. + + Returns: + True if all constraint groups are valid. + + Raises: + IncoherenceBetweenMatricesLength: If any validation checks fail. + """ + storage_service = self.storage_service.get_storage(study) + file_study = storage_service.get_raw(study) + grouped_constraints = self.get_grouped_constraints(study) + invalid_groups = {} + + for group_name, bcs in grouped_constraints.items(): try: - index = [value["id"] for value in config_values].index(constraint_id) - config_value = config_values[index] - return BindingConstraintManager.process_constraint(config_value) - except ValueError: - return None - - binding_constraint = [] - for config_value in config_values: - new_config = BindingConstraintManager.process_constraint(config_value) - binding_constraint.append(new_config) - return binding_constraint + _validate_binding_constraints(file_study, bcs) + except MatrixWidthMismatchError as e: + invalid_groups[group_name] = e.detail + + if invalid_groups: + err_msg = ", ".join(f"'{grp}': {msg}" for grp, msg in sorted(invalid_groups.items())) + raise MatrixWidthMismatchError(err_msg) + + return True def create_binding_constraint( self, study: Study, - data: BindingConstraintPropertiesWithName, - ) -> None: + data: ConstraintCreation, + ) -> ConstraintOutput: bc_id = transform_name_to_id(data.name) + version = int(study.version) if not bc_id: raise InvalidConstraintName(f"Invalid binding constraint name: {data.name}.") - file_study = self.storage_service.get_storage(study).get_raw(study) - binding_constraints = self.get_binding_constraint(study, None) - existing_ids = {bc.id for bc in binding_constraints} # type: ignore - - if bc_id in existing_ids: + if bc_id in {bc.id for bc in self.get_binding_constraints(study)}: raise DuplicateConstraintName(f"A binding constraint with the same name already exists: {bc_id}.") - command = CreateBindingConstraint( - name=data.name, - enabled=data.enabled, - time_step=data.time_step, - operator=data.operator, - coeffs=data.coeffs, - values=data.values, - filter_year_by_year=data.filter_year_by_year, - filter_synthesis=data.filter_synthesis, - comments=data.comments or "", - command_context=self.storage_service.variant_study_service.command_factory.command_context, - ) + check_attributes_coherence(data, version) + + new_constraint = {"name": data.name, **json.loads(data.json(exclude={"terms", "name"}, exclude_none=True))} + args = { + **new_constraint, + "command_context": self.storage_service.variant_study_service.command_factory.command_context, + } + if data.terms: + args["coeffs"] = self.terms_to_coeffs(data.terms) + + command = CreateBindingConstraint(**args) + + # Validates the matrices. Needed when the study is a variant because we only append the command to the list + if isinstance(study, VariantStudy): + time_step = data.time_step or BindingConstraintFrequency.HOURLY + command.validates_and_fills_matrices( + time_step=time_step, specific_matrices=None, version=version, create=True + ) + + file_study = self.storage_service.get_storage(study).get_raw(study) execute_or_add_commands(study, file_study, [command], self.storage_service) + # Processes the constraints to add them inside the endpoint response. + new_constraint["id"] = bc_id + return self.constraint_model_adapter(new_constraint, version) + def update_binding_constraint( self, study: Study, binding_constraint_id: str, - data: UpdateBindingConstProps, - ) -> None: + data: ConstraintInput, + ) -> ConstraintOutput: file_study = self.storage_service.get_storage(study).get_raw(study) - constraint = self.get_binding_constraint(study, binding_constraint_id) - if not isinstance(constraint, BindingConstraintDTO): - raise BindingConstraintNotFoundError(study.id) - - if data.key == "time_step" and data.value != constraint.time_step: + existing_constraint = self.get_binding_constraint(study, binding_constraint_id) + study_version = int(study.version) + check_attributes_coherence(data, study_version) + + upd_constraint = { + "id": binding_constraint_id, + **json.loads(data.json(exclude={"terms", "name"}, exclude_none=True)), + } + args = { + **upd_constraint, + "command_context": self.storage_service.variant_study_service.command_factory.command_context, + } + if data.terms: + args["coeffs"] = self.terms_to_coeffs(data.terms) + + if data.time_step is not None and data.time_step != existing_constraint.time_step: # The user changed the time step, we need to update the matrix accordingly - matrix = { - BindingConstraintFrequency.HOURLY.value: default_bc_hourly, - BindingConstraintFrequency.DAILY.value: default_bc_weekly_daily, - BindingConstraintFrequency.WEEKLY.value: default_bc_weekly_daily, - }[data.value].tolist() - else: - # The user changed another property, we keep the matrix as it is - matrix = constraint.values + args = _replace_matrices_according_to_frequency_and_version(data, study_version, args) + + command = UpdateBindingConstraint(**args) + + # Validates the matrices. Needed when the study is a variant because we only append the command to the list + if isinstance(study, VariantStudy): + updated_matrices = [term for term in TERM_MATRICES if getattr(data, term)] + time_step = data.time_step or existing_constraint.time_step + command.validates_and_fills_matrices( + time_step=time_step, specific_matrices=updated_matrices, version=study_version, create=False + ) - command = UpdateBindingConstraint( - id=constraint.id, - enabled=data.value if data.key == "enabled" else constraint.enabled, - time_step=data.value if data.key == "time_step" else constraint.time_step, - operator=data.value if data.key == "operator" else constraint.operator, - coeffs=BindingConstraintManager.constraints_to_coeffs(constraint), - values=matrix, - filter_year_by_year=data.value if data.key == "filterByYear" else constraint.filter_year_by_year, - filter_synthesis=data.value if data.key == "filterSynthesis" else constraint.filter_synthesis, - comments=data.value if data.key == "comments" else constraint.comments, - command_context=self.storage_service.variant_study_service.command_factory.command_context, - ) execute_or_add_commands(study, file_study, [command], self.storage_service) - @staticmethod - def find_constraint_term_id(constraints_term: List[ConstraintTermDTO], constraint_term_id: str) -> int: - try: - index = [elm.id for elm in constraints_term].index(constraint_term_id) - return index - except ValueError: - return -1 - - def add_new_constraint_term( + # Constructs the endpoint response. + upd_constraint["name"] = existing_constraint.name + upd_constraint["type"] = upd_constraint.get("time_step", existing_constraint.time_step) + upd_constraint["terms"] = data.terms or existing_constraint.terms + new_fields = ["enabled", "operator", "comments", "terms"] + if study_version >= 830: + new_fields.extend(["filter_year_by_year", "filter_synthesis"]) + if study_version >= 870: + new_fields.append("group") + for field in new_fields: + if field not in upd_constraint: + upd_constraint[field] = getattr(data, field) or getattr(existing_constraint, field) + return self.constraint_model_adapter(upd_constraint, study_version) + + def update_binding_constraints( self, study: Study, - binding_constraint_id: str, - constraint_term: ConstraintTermDTO, - ) -> None: + bcs_by_ids: t.Mapping[str, ConstraintInput], + ) -> t.Mapping[str, ConstraintOutput]: + """ + Updates multiple binding constraints within a study. + + Args: + study: The study from which to update the constraints. + bcs_by_ids: A mapping of binding constraint IDs to their updated configurations. + + Returns: + A dictionary of the updated binding constraints, indexed by their IDs. + + Raises: + BindingConstraintNotFound: If any of the specified binding constraint IDs are not found. + """ + updated_constraints = {} + for bc_id, data in bcs_by_ids.items(): + updated_constraints[bc_id] = self.update_binding_constraint(study, bc_id, data) + return updated_constraints + + def remove_binding_constraint(self, study: Study, binding_constraint_id: str) -> None: + """ + Removes a binding constraint from a study. + + Args: + study: The study from which to remove the constraint. + binding_constraint_id: The ID of the binding constraint to remove. + + Raises: + BindingConstraintNotFound: If no binding constraint with the specified ID is found. + """ + # Check the existence of the binding constraint before removing it + bc = self.get_binding_constraint(study, binding_constraint_id) + command_context = self.storage_service.variant_study_service.command_factory.command_context file_study = self.storage_service.get_storage(study).get_raw(study) - constraint = self.get_binding_constraint(study, binding_constraint_id) - if not isinstance(constraint, BindingConstraintDTO): - raise BindingConstraintNotFoundError(study.id) - - if constraint_term.data is None: - raise MissingDataError("Add new constraint term : data is missing") - - constraint_id = constraint_term.data.generate_id() - constraints_term = constraint.constraints or [] - if BindingConstraintManager.find_constraint_term_id(constraints_term, constraint_id) >= 0: - raise ConstraintAlreadyExistError(study.id) - - constraints_term.append( - ConstraintTermDTO( - id=constraint_id, - weight=constraint_term.weight if constraint_term.weight is not None else 0.0, - offset=constraint_term.offset, - data=constraint_term.data, - ) - ) - coeffs = {} - for term in constraints_term: - coeffs[term.id] = [term.weight] - if term.offset is not None: - coeffs[term.id].append(term.offset) + command = RemoveBindingConstraint(id=bc.id, command_context=command_context) + execute_or_add_commands(study, file_study, [command], self.storage_service) + def _update_constraint_with_terms( + self, study: Study, bc: ConstraintOutput, terms: t.Mapping[str, ConstraintTerm] + ) -> None: + coeffs = { + term_id: [term.weight, term.offset] if term.offset else [term.weight] for term_id, term in terms.items() + } command = UpdateBindingConstraint( - id=constraint.id, - enabled=constraint.enabled, - time_step=constraint.time_step, - operator=constraint.operator, + id=bc.id, coeffs=coeffs, - values=constraint.values, - comments=constraint.comments, - filter_year_by_year=constraint.filter_year_by_year, - filter_synthesis=constraint.filter_synthesis, command_context=self.storage_service.variant_study_service.command_factory.command_context, ) + file_study = self.storage_service.get_storage(study).get_raw(study) execute_or_add_commands(study, file_study, [command], self.storage_service) - def update_constraint_term( + def update_constraint_terms( self, study: Study, binding_constraint_id: str, - term: Union[ConstraintTermDTO, str], + constraint_terms: t.Sequence[ConstraintTerm], + update_mode: str = "replace", ) -> None: - file_study = self.storage_service.get_storage(study).get_raw(study) - constraint = self.get_binding_constraint(study, binding_constraint_id) - - if not isinstance(constraint, BindingConstraintDTO): - raise BindingConstraintNotFoundError(study.id) - - constraint_terms = constraint.constraints # existing constraint terms - if constraint_terms is None: - raise NoConstraintError(study.id) - - term_id = term.id if isinstance(term, ConstraintTermDTO) else term - if term_id is None: - raise ConstraintIdNotFoundError(study.id) - - term_id_index = BindingConstraintManager.find_constraint_term_id(constraint_terms, term_id) - if term_id_index < 0: - raise ConstraintIdNotFoundError(study.id) + """ + Update or add the specified constraint terms. + + Args: + study: The study from which to update the binding constraint. + binding_constraint_id: The ID of the binding constraint to update. + constraint_terms: The constraint terms to update. + update_mode: The update mode, either "replace" or "add". + """ + if update_mode == "add": + for term in constraint_terms: + if term.data is None: + raise InvalidConstraintTerm(binding_constraint_id, term.json()) - if isinstance(term, ConstraintTermDTO): - updated_term_id = term.data.generate_id() if term.data else term_id - current_constraint = constraint_terms[term_id_index] - - constraint_terms[term_id_index] = ConstraintTermDTO( - id=updated_term_id, - weight=term.weight or current_constraint.weight, - offset=term.offset, - data=term.data or current_constraint.data, - ) - else: - del constraint_terms[term_id_index] - - coeffs = {term.id: [term.weight, term.offset] if term.offset else [term.weight] for term in constraint_terms} + constraint = self.get_binding_constraint(study, binding_constraint_id) + existing_terms = collections.OrderedDict((term.generate_id(), term) for term in constraint.terms) + updated_terms = collections.OrderedDict((term.generate_id(), term) for term in constraint_terms) + + if update_mode == "replace": + missing_terms = set(updated_terms) - set(existing_terms) + if missing_terms: + raise ConstraintTermNotFound(binding_constraint_id, *missing_terms) + elif update_mode == "add": + duplicate_terms = set(updated_terms) & set(existing_terms) + if duplicate_terms: + raise DuplicateConstraintTerm(binding_constraint_id, *duplicate_terms) + else: # pragma: no cover + raise NotImplementedError(f"Unsupported update mode: {update_mode}") + + existing_terms.update(updated_terms) + self._update_constraint_with_terms(study, constraint, existing_terms) + + def create_constraint_terms( + self, study: Study, binding_constraint_id: str, constraint_terms: t.Sequence[ConstraintTerm] + ) -> None: + """ + Adds new constraint terms to an existing binding constraint. - command = UpdateBindingConstraint( - id=constraint.id, - enabled=constraint.enabled, - time_step=constraint.time_step, - operator=constraint.operator, - coeffs=coeffs, - values=constraint.values, - filter_year_by_year=constraint.filter_year_by_year, - filter_synthesis=constraint.filter_synthesis, - comments=constraint.comments, - command_context=self.storage_service.variant_study_service.command_factory.command_context, - ) - execute_or_add_commands(study, file_study, [command], self.storage_service) + Args: + study: The study from which to update the binding constraint. + binding_constraint_id: The ID of the binding constraint to update. + constraint_terms: The constraint terms to add. + """ + return self.update_constraint_terms(study, binding_constraint_id, constraint_terms, update_mode="add") - # FIXME create a dedicated delete service def remove_constraint_term( self, study: Study, binding_constraint_id: str, term_id: str, ) -> None: - return self.update_constraint_term(study, binding_constraint_id, term_id) + """ + Remove a constraint term from an existing binding constraint. + + Args: + study: The study from which to update the binding constraint. + binding_constraint_id: The ID of the binding constraint to update. + term_id: The ID of the term to remove. + """ + constraint = self.get_binding_constraint(study, binding_constraint_id) + existing_terms = collections.OrderedDict((term.generate_id(), term) for term in constraint.terms) + removed_term = existing_terms.pop(term_id, None) + if removed_term is None: + raise ConstraintTermNotFound(binding_constraint_id, term_id) + self._update_constraint_with_terms(study, constraint, existing_terms) + + @staticmethod + def get_table_schema() -> JSON: + return ConstraintOutput870.schema() + + +def _replace_matrices_according_to_frequency_and_version( + data: ConstraintInput, version: int, args: t.Dict[str, t.Any] +) -> t.Dict[str, t.Any]: + if version < 870: + if "values" not in args: + matrix = { + BindingConstraintFrequency.HOURLY.value: default_bc_hourly_86, + BindingConstraintFrequency.DAILY.value: default_bc_weekly_daily_86, + BindingConstraintFrequency.WEEKLY.value: default_bc_weekly_daily_86, + }[data.time_step].tolist() + args["values"] = matrix + else: + matrix = { + BindingConstraintFrequency.HOURLY.value: default_bc_hourly_87, + BindingConstraintFrequency.DAILY.value: default_bc_weekly_daily_87, + BindingConstraintFrequency.WEEKLY.value: default_bc_weekly_daily_87, + }[data.time_step].tolist() + for term in TERM_MATRICES: + if term not in args: + args[term] = matrix + return args + + +def check_attributes_coherence(data: t.Union[ConstraintCreation, ConstraintInput], study_version: int) -> None: + if study_version < 870: + if data.group: + raise InvalidFieldForVersionError( + f"You cannot specify a group as your study version is older than v8.7: {data.group}" + ) + if any([data.less_term_matrix, data.equal_term_matrix, data.greater_term_matrix]): + raise InvalidFieldForVersionError("You cannot fill a 'matrix_term' as these values refer to v8.7+ studies") + elif data.values: + raise InvalidFieldForVersionError("You cannot fill 'values' as it refers to the matrix before v8.7") diff --git a/antarest/study/business/link_management.py b/antarest/study/business/link_management.py index 971b0ca376..375a539fd8 100644 --- a/antarest/study/business/link_management.py +++ b/antarest/study/business/link_management.py @@ -1,12 +1,19 @@ -from typing import Any, Dict, List, Optional +import typing as t from pydantic import BaseModel +from antarest.core.exceptions import ConfigFileNotFound +from antarest.core.model import JSON +from antarest.study.business.all_optional_meta import AllOptionalMetaclass, camel_case_model from antarest.study.business.utils import execute_or_add_commands -from antarest.study.model import Study +from antarest.study.model import RawStudy +from antarest.study.storage.rawstudy.model.filesystem.config.links import LinkProperties from antarest.study.storage.storage_service import StudyStorageService from antarest.study.storage.variantstudy.model.command.create_link import CreateLink from antarest.study.storage.variantstudy.model.command.remove_link import RemoveLink +from antarest.study.storage.variantstudy.model.command.update_config import UpdateConfig + +_ALL_LINKS_PATH = "input/links" class LinkUIDTO(BaseModel): @@ -18,37 +25,29 @@ class LinkUIDTO(BaseModel): class LinkInfoDTO(BaseModel): area1: str area2: str - ui: Optional[LinkUIDTO] = None - - -class GenericElement(BaseModel): - id: str - name: str - - -class GenericItem(BaseModel): - element: GenericElement - item_list: List[GenericElement] + ui: t.Optional[LinkUIDTO] = None -class AllCLustersAndLinks(BaseModel): - links: List[GenericItem] - clusters: List[GenericItem] +@camel_case_model +class LinkOutput(LinkProperties, metaclass=AllOptionalMetaclass, use_none=True): + """ + DTO object use to get the link information. + """ class LinkManager: def __init__(self, storage_service: StudyStorageService) -> None: self.storage_service = storage_service - def get_all_links(self, study: Study, with_ui: bool = False) -> List[LinkInfoDTO]: + def get_all_links(self, study: RawStudy, with_ui: bool = False) -> t.List[LinkInfoDTO]: file_study = self.storage_service.get_storage(study).get_raw(study) result = [] for area_id, area in file_study.config.areas.items(): - links_config: Optional[Dict[str, Any]] = None + links_config: t.Optional[t.Dict[str, t.Any]] = None if with_ui: links_config = file_study.tree.get(["input", "links", area_id, "properties"]) for link in area.links: - ui_info: Optional[LinkUIDTO] = None + ui_info: t.Optional[LinkUIDTO] = None if with_ui and links_config and link in links_config: ui_info = LinkUIDTO( color=f"{links_config[link].get('colorr', '163')},{links_config[link].get('colorg', '163')},{links_config[link].get('colorb', '163')}", @@ -59,7 +58,7 @@ def get_all_links(self, study: Study, with_ui: bool = False) -> List[LinkInfoDTO return result - def create_link(self, study: Study, link_creation_info: LinkInfoDTO) -> LinkInfoDTO: + def create_link(self, study: RawStudy, link_creation_info: LinkInfoDTO) -> LinkInfoDTO: storage_service = self.storage_service.get_storage(study) file_study = storage_service.get_raw(study) command = CreateLink( @@ -73,7 +72,7 @@ def create_link(self, study: Study, link_creation_info: LinkInfoDTO) -> LinkInfo area2=link_creation_info.area2, ) - def delete_link(self, study: Study, area1_id: str, area2_id: str) -> None: + def delete_link(self, study: RawStudy, area1_id: str, area2_id: str) -> None: file_study = self.storage_service.get_storage(study).get_raw(study) command = RemoveLink( area1=area1_id, @@ -81,3 +80,67 @@ def delete_link(self, study: Study, area1_id: str, area2_id: str) -> None: command_context=self.storage_service.variant_study_service.command_factory.command_context, ) execute_or_add_commands(study, file_study, [command], self.storage_service) + + def get_all_links_props(self, study: RawStudy) -> t.Mapping[t.Tuple[str, str], LinkOutput]: + """ + Retrieves all links properties from the study. + + Args: + study: The raw study object. + Returns: + A mapping of link IDS `(area1_id, area2_id)` to link properties. + Raises: + ConfigFileNotFound: if a configuration file is not found. + """ + file_study = self.storage_service.get_storage(study).get_raw(study) + + # Get the link information from the `input/links/{area1}/properties.ini` file. + path = _ALL_LINKS_PATH + try: + links_cfg = file_study.tree.get(path.split("/"), depth=5) + except KeyError: + raise ConfigFileNotFound(path) from None + + # areas_cfg contains a dictionary where the keys are the area IDs, + # and the values are objects that can be converted to `LinkFolder`. + links_by_ids = {} + for area1_id, entries in links_cfg.items(): + property_map = entries.get("properties") or {} + for area2_id, properties_cfg in property_map.items(): + area1_id, area2_id = sorted([area1_id, area2_id]) + properties = LinkProperties(**properties_cfg) + links_by_ids[(area1_id, area2_id)] = LinkOutput(**properties.dict(by_alias=False)) + + return links_by_ids + + def update_links_props( + self, + study: RawStudy, + update_links_by_ids: t.Mapping[t.Tuple[str, str], LinkOutput], + ) -> t.Mapping[t.Tuple[str, str], LinkOutput]: + old_links_by_ids = self.get_all_links_props(study) + new_links_by_ids = {} + file_study = self.storage_service.get_storage(study).get_raw(study) + commands = [] + for (area1, area2), update_link_dto in update_links_by_ids.items(): + # Update the link properties. + old_link_dto = old_links_by_ids[(area1, area2)] + new_link_dto = old_link_dto.copy(update=update_link_dto.dict(by_alias=False, exclude_none=True)) + new_links_by_ids[(area1, area2)] = new_link_dto + + # Convert the DTO to a configuration object and update the configuration file. + properties = LinkProperties(**new_link_dto.dict(by_alias=False)) + path = f"{_ALL_LINKS_PATH}/{area1}/properties" + cmd = UpdateConfig( + target=path, + data={area2: properties.to_config()}, + command_context=self.storage_service.variant_study_service.command_factory.command_context, + ) + commands.append(cmd) + + execute_or_add_commands(study, file_study, commands, self.storage_service) + return new_links_by_ids + + @staticmethod + def get_table_schema() -> JSON: + return LinkOutput.schema() diff --git a/antarest/study/business/table_mode_management.py b/antarest/study/business/table_mode_management.py index 43808e8248..65687af9c9 100644 --- a/antarest/study/business/table_mode_management.py +++ b/antarest/study/business/table_mode_management.py @@ -1,579 +1,259 @@ -from typing import Any, Dict, List, Optional, TypedDict, Union - -from pydantic import StrictFloat -from pydantic.types import StrictBool, StrictInt, StrictStr - -from antarest.study.business.areas.properties_management import AdequacyPatchMode -from antarest.study.business.areas.renewable_management import TimeSeriesInterpretation -from antarest.study.business.binding_constraint_management import BindingConstraintManager +import collections +import typing as t + +import numpy as np +import pandas as pd + +from antarest.core.model import JSON +from antarest.study.business.area_management import AreaManager, AreaOutput +from antarest.study.business.areas.renewable_management import RenewableClusterInput, RenewableManager +from antarest.study.business.areas.st_storage_management import STStorageInput, STStorageManager +from antarest.study.business.areas.thermal_management import ThermalClusterInput, ThermalManager +from antarest.study.business.binding_constraint_management import BindingConstraintManager, ConstraintInput from antarest.study.business.enum_ignore_case import EnumIgnoreCase -from antarest.study.business.utils import FormFieldsBaseModel, execute_or_add_commands -from antarest.study.common.default_values import FilteringOptions, LinkProperties, NodalOptimization +from antarest.study.business.link_management import LinkManager, LinkOutput from antarest.study.model import RawStudy -from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import BindingConstraintFrequency -from antarest.study.storage.rawstudy.model.filesystem.config.thermal import LawOption, LocalTSGenerationBehavior -from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy -from antarest.study.storage.storage_service import StudyStorageService -from antarest.study.storage.variantstudy.model.command.icommand import ICommand -from antarest.study.storage.variantstudy.model.command.update_binding_constraint import UpdateBindingConstraint -from antarest.study.storage.variantstudy.model.command.update_config import UpdateConfig - - -class TableTemplateType(EnumIgnoreCase): - AREA = "area" - LINK = "link" - CLUSTER = "cluster" - RENEWABLE = "renewable" - BINDING_CONSTRAINT = "binding constraint" - - -class AssetType(EnumIgnoreCase): - AC = "ac" - DC = "dc" - GAZ = "gaz" - VIRT = "virt" - OTHER = "other" - - -class TransmissionCapacity(EnumIgnoreCase): - INFINITE = "infinite" - IGNORE = "ignore" - ENABLED = "enabled" - - -class BindingConstraintOperator(EnumIgnoreCase): - LESS = "less" - GREATER = "greater" - BOTH = "both" - EQUAL = "equal" - - -class AreaColumns(FormFieldsBaseModel): - # Optimization - Nodal optimization - non_dispatchable_power: Optional[StrictBool] - dispatchable_hydro_power: Optional[StrictBool] - other_dispatchable_power: Optional[StrictBool] - average_unsupplied_energy_cost: Optional[Union[StrictFloat, StrictInt]] - spread_unsupplied_energy_cost: Optional[Union[StrictFloat, StrictInt]] - average_spilled_energy_cost: Optional[Union[StrictFloat, StrictInt]] - spread_spilled_energy_cost: Optional[Union[StrictFloat, StrictInt]] - # Optimization - Filtering - filter_synthesis: Optional[StrictStr] - filter_year_by_year: Optional[StrictStr] - # Adequacy patch - adequacy_patch_mode: Optional[AdequacyPatchMode] - - -class LinkColumns(FormFieldsBaseModel): - hurdles_cost: Optional[StrictBool] - loop_flow: Optional[StrictBool] - use_phase_shifter: Optional[StrictBool] - transmission_capacities: Optional[TransmissionCapacity] - asset_type: Optional[AssetType] - link_style: Optional[StrictStr] - link_width: Optional[StrictInt] - display_comments: Optional[StrictBool] - filter_synthesis: Optional[StrictStr] - filter_year_by_year: Optional[StrictStr] - - -class ClusterColumns(FormFieldsBaseModel): - group: Optional[StrictStr] - enabled: Optional[StrictBool] - must_run: Optional[StrictBool] - unit_count: Optional[StrictInt] - nominal_capacity: Optional[StrictInt] - min_stable_power: Optional[StrictInt] - spinning: Optional[StrictInt] - min_up_time: Optional[StrictInt] - min_down_time: Optional[StrictInt] - co2: Optional[StrictInt] - marginal_cost: Optional[StrictInt] - fixed_cost: Optional[StrictInt] - startup_cost: Optional[StrictInt] - market_bid_cost: Optional[StrictInt] - spread_cost: Optional[StrictInt] - ts_gen: Optional[LocalTSGenerationBehavior] - volatility_forced: Optional[StrictInt] - volatility_planned: Optional[StrictInt] - law_forced: Optional[LawOption] - law_planned: Optional[LawOption] - +from antarest.study.storage.rawstudy.model.filesystem.folder_node import ChildNotFoundError -class RenewableColumns(FormFieldsBaseModel): - group: Optional[StrictStr] - ts_interpretation: Optional[TimeSeriesInterpretation] - enabled: Optional[StrictBool] - unit_count: Optional[StrictInt] - nominal_capacity: Optional[StrictInt] +_TableIndex = str # row name +_TableColumn = str # column name +_CellValue = t.Any # cell value (str, int, float, bool, enum, etc.) +TableDataDTO = t.Mapping[_TableIndex, t.Mapping[_TableColumn, _CellValue]] -class BindingConstraintColumns(FormFieldsBaseModel): - type: Optional[BindingConstraintFrequency] - operator: Optional[BindingConstraintOperator] - enabled: Optional[StrictBool] - - -class ColumnInfo(TypedDict): - path: str - default_value: Any - - -class PathVars(TypedDict, total=False): - # Area - id: str - # Link - area1: str - area2: str - # Cluster, Renewable - area: str - cluster: str - - -AREA_PATH = "input/areas/{area}" -THERMAL_PATH = "input/thermal/areas" -LINK_GLOB_PATH = "input/links/{area1}/properties" -LINK_PATH = f"{LINK_GLOB_PATH}/{{area2}}" -CLUSTER_GLOB_PATH = "input/thermal/clusters/{area}/list" -CLUSTER_PATH = f"{CLUSTER_GLOB_PATH}/{{cluster}}" -RENEWABLE_GLOB_PATH = "input/renewables/clusters/{area}/list" -RENEWABLE_PATH = f"{RENEWABLE_GLOB_PATH}/{{cluster}}" -BINDING_CONSTRAINT_PATH = "input/bindingconstraints/bindingconstraints" - -FIELDS_INFO_BY_TYPE: Dict[TableTemplateType, Dict[str, ColumnInfo]] = { - TableTemplateType.AREA: { - "non_dispatchable_power": { - "path": f"{AREA_PATH}/optimization/nodal optimization/non-dispatchable-power", - "default_value": NodalOptimization.NON_DISPATCHABLE_POWER, - }, - "dispatchable_hydro_power": { - "path": f"{AREA_PATH}/optimization/nodal optimization/dispatchable-hydro-power", - "default_value": NodalOptimization.DISPATCHABLE_HYDRO_POWER, - }, - "other_dispatchable_power": { - "path": f"{AREA_PATH}/optimization/nodal optimization/other-dispatchable-power", - "default_value": NodalOptimization.OTHER_DISPATCHABLE_POWER, - }, - "average_unsupplied_energy_cost": { - "path": f"{THERMAL_PATH}/unserverdenergycost/{{area}}", - "default_value": NodalOptimization.SPREAD_UNSUPPLIED_ENERGY_COST, - }, - "spread_unsupplied_energy_cost": { - "path": f"{AREA_PATH}/optimization/nodal optimization/spread-unsupplied-energy-cost", - "default_value": NodalOptimization.SPREAD_UNSUPPLIED_ENERGY_COST, - }, - "average_spilled_energy_cost": { - "path": f"{THERMAL_PATH}/spilledenergycost/{{area}}", - "default_value": NodalOptimization.SPREAD_SPILLED_ENERGY_COST, - }, - "spread_spilled_energy_cost": { - "path": f"{AREA_PATH}/optimization/nodal optimization/spread-spilled-energy-cost", - "default_value": NodalOptimization.SPREAD_SPILLED_ENERGY_COST, - }, - "filter_synthesis": { - "path": f"{AREA_PATH}/optimization/filtering/filter-synthesis", - "default_value": FilteringOptions.FILTER_SYNTHESIS, - }, - "filter_year_by_year": { - "path": f"{AREA_PATH}/optimization/filtering/filter-year-by-year", - "default_value": FilteringOptions.FILTER_YEAR_BY_YEAR, - }, - "adequacy_patch_mode": { - "path": f"{AREA_PATH}/adequacy_patch/adequacy-patch/adequacy-patch-mode", - "default_value": AdequacyPatchMode.OUTSIDE.value, - }, - }, - TableTemplateType.LINK: { - "hurdles_cost": { - "path": f"{LINK_PATH}/hurdles-cost", - "default_value": LinkProperties.HURDLES_COST, - }, - "loop_flow": { - "path": f"{LINK_PATH}/loop-flow", - "default_value": LinkProperties.LOOP_FLOW, - }, - "use_phase_shifter": { - "path": f"{LINK_PATH}/use-phase-shifter", - "default_value": LinkProperties.USE_PHASE_SHIFTER, - }, - "transmission_capacities": { - "path": f"{LINK_PATH}/transmission-capacities", - "default_value": LinkProperties.TRANSMISSION_CAPACITIES, - }, - "asset_type": { - "path": f"{LINK_PATH}/asset-type", - "default_value": LinkProperties.ASSET_TYPE, - }, - "link_style": { - "path": f"{LINK_PATH}/link-style", - "default_value": LinkProperties.LINK_STYLE, - }, - "link_width": { - "path": f"{LINK_PATH}/link-width", - "default_value": LinkProperties.LINK_WIDTH, - }, - "display_comments": { - "path": f"{LINK_PATH}/display-comments", - "default_value": LinkProperties.DISPLAY_COMMENTS, - }, - "filter_synthesis": { - "path": f"{LINK_PATH}/filter-synthesis", - "default_value": FilteringOptions.FILTER_SYNTHESIS, - }, - "filter_year_by_year": { - "path": f"{LINK_PATH}/filter-year-by-year", - "default_value": FilteringOptions.FILTER_YEAR_BY_YEAR, - }, - }, - TableTemplateType.CLUSTER: { - "group": { - "path": f"{CLUSTER_PATH}/group", - "default_value": "", - }, - "enabled": { - "path": f"{CLUSTER_PATH}/enabled", - "default_value": True, - }, - "must_run": { - "path": f"{CLUSTER_PATH}/must-run", - "default_value": False, - }, - "unit_count": { - "path": f"{CLUSTER_PATH}/unitcount", - "default_value": 0, - }, - "nominal_capacity": { - "path": f"{CLUSTER_PATH}/nominalcapacity", - "default_value": 0, - }, - "min_stable_power": { - "path": f"{CLUSTER_PATH}/min-stable-power", - "default_value": 0, - }, - "spinning": { - "path": f"{CLUSTER_PATH}/spinning", - "default_value": 0, - }, - "min_up_time": { - "path": f"{CLUSTER_PATH}/min-up-time", - "default_value": 1, - }, - "min_down_time": { - "path": f"{CLUSTER_PATH}/min-down-time", - "default_value": 1, - }, - "co2": { - "path": f"{CLUSTER_PATH}/co2", - "default_value": 0, - }, - "marginal_cost": { - "path": f"{CLUSTER_PATH}/marginal-cost", - "default_value": 0, - }, - "fixed_cost": { - "path": f"{CLUSTER_PATH}/fixed-cost", - "default_value": 0, - }, - "startup_cost": { - "path": f"{CLUSTER_PATH}/startup-cost", - "default_value": 0, - }, - "market_bid_cost": { - "path": f"{CLUSTER_PATH}/market-bid-cost", - "default_value": 0, - }, - "spread_cost": { - "path": f"{CLUSTER_PATH}/spread-cost", - "default_value": 0, - }, - "ts_gen": { - "path": f"{CLUSTER_PATH}/gen-ts", - "default_value": LocalTSGenerationBehavior.USE_GLOBAL.value, - }, - "volatility_forced": { - "path": f"{CLUSTER_PATH}/volatility.forced", - "default_value": 0, - }, - "volatility_planned": { - "path": f"{CLUSTER_PATH}/volatility.planned", - "default_value": 0, - }, - "law_forced": { - "path": f"{CLUSTER_PATH}/law.forced", - "default_value": LawOption.UNIFORM.value, - }, - "law_planned": { - "path": f"{CLUSTER_PATH}/law.planned", - "default_value": LawOption.UNIFORM.value, - }, - }, - TableTemplateType.RENEWABLE: { - "group": { - "path": f"{RENEWABLE_PATH}/group", - "default_value": "", - }, - "ts_interpretation": { - "path": f"{RENEWABLE_PATH}/ts-interpretation", - "default_value": TimeSeriesInterpretation.POWER_GENERATION.value, - }, - "enabled": { - "path": f"{RENEWABLE_PATH}/enabled", - "default_value": True, - }, - "unit_count": { - "path": f"{RENEWABLE_PATH}/unitcount", - "default_value": 0, - }, - "nominal_capacity": { - "path": f"{RENEWABLE_PATH}/nominalcapacity", - "default_value": 0, - }, - }, - TableTemplateType.BINDING_CONSTRAINT: { - "type": { - "path": f"{BINDING_CONSTRAINT_PATH}/type", - "default_value": BindingConstraintFrequency.HOURLY.value, - }, - "operator": { - "path": f"{BINDING_CONSTRAINT_PATH}/operator", - "default_value": BindingConstraintOperator.LESS.value, - }, - "enabled": { - "path": f"{BINDING_CONSTRAINT_PATH}/enabled", - "default_value": True, - }, - }, -} - -COLUMNS_MODELS_BY_TYPE = { - TableTemplateType.AREA: AreaColumns, - TableTemplateType.LINK: LinkColumns, - TableTemplateType.CLUSTER: ClusterColumns, - TableTemplateType.RENEWABLE: RenewableColumns, - TableTemplateType.BINDING_CONSTRAINT: BindingConstraintColumns, -} - -ColumnsModelTypes = Union[ - AreaColumns, - LinkColumns, - ClusterColumns, - RenewableColumns, - BindingConstraintColumns, -] - - -def _get_glob_object(file_study: FileStudy, table_type: TableTemplateType) -> Dict[str, Any]: +class TableModeType(EnumIgnoreCase): """ - Retrieves the fields of an object according to its type (area, link, thermal cluster...). - - Args: - file_study: A file study from which the configuration can be read. - table_type: Type of the object. - - Returns: - Dictionary containing the fields used in Table mode. - - Raises: - ChildNotFoundError: if one of the Area IDs is not found in the configuration. + Table types. + + This enum is used to define the different types of tables that can be created + by the user to leverage the editing capabilities of multiple objects at once. + + Attributes: + AREA: Area table. + LINK: Link table. + THERMAL: Thermal clusters table. + RENEWABLE: Renewable clusters table. + ST_STORAGE: Short-Term Storages table. + BINDING_CONSTRAINT: Binding constraints table. """ - # sourcery skip: extract-method - if table_type == TableTemplateType.AREA: - info_map: Dict[str, Any] = file_study.tree.get(url=AREA_PATH.format(area="*").split("/"), depth=3) - area_ids = list(file_study.config.areas) - # If there is only one ID in the `area_ids`, the result returned from - # the `file_study.tree.get` call will be a single object. - # On the other hand, if there are multiple values in `area_ids`, - # the result will be a dictionary where the keys are the IDs, - # and the values are the corresponding objects. - if len(area_ids) == 1: - info_map = {area_ids[0]: info_map} - # Add thermal fields in info_map - thermal_fields = file_study.tree.get(THERMAL_PATH.split("/")) - for field, field_props in thermal_fields.items(): - for area_id, value in field_props.items(): - if area_id in info_map: - info_map[area_id][field] = value - return info_map - url = { - TableTemplateType.LINK: LINK_GLOB_PATH.format(area1="*").split("/"), - TableTemplateType.CLUSTER: CLUSTER_GLOB_PATH.format(area="*").split("/"), - TableTemplateType.RENEWABLE: RENEWABLE_GLOB_PATH.format(area="*").split("/"), - TableTemplateType.BINDING_CONSTRAINT: BINDING_CONSTRAINT_PATH.split("/"), - }[table_type] - - return file_study.tree.get(url) + AREA = "areas" + LINK = "links" + THERMAL = "thermals" + RENEWABLE = "renewables" + # Avoid "storages" because we may have "lt-storages" (long-term storages) in the future + ST_STORAGE = "st-storages" + # Avoid "constraints" because we may have other kinds of constraints in the future + BINDING_CONSTRAINT = "binding-constraints" + + @classmethod + def _missing_(cls, value: object) -> t.Optional["EnumIgnoreCase"]: + if isinstance(value, str): + # handle aliases of old table types + value = value.upper() + aliases = { + "AREA": cls.AREA, + "LINK": cls.LINK, + "CLUSTER": cls.THERMAL, + "RENEWABLE": cls.RENEWABLE, + "BINDING CONSTRAINT": cls.BINDING_CONSTRAINT, + } + if value in aliases: + return aliases[value] + return super()._missing_(value) class TableModeManager: - def __init__(self, storage_service: StudyStorageService) -> None: - self.storage_service = storage_service - - def get_table_data( + def __init__( self, - study: RawStudy, - table_type: TableTemplateType, - columns: List[str], - ) -> Dict[str, ColumnsModelTypes]: - file_study = self.storage_service.get_storage(study).get_raw(study) - columns_model = COLUMNS_MODELS_BY_TYPE[table_type] - fields_info = FIELDS_INFO_BY_TYPE[table_type] - glob_object = _get_glob_object(file_study, table_type) - - def get_column_value(col: str, data: Dict[str, Any]) -> Any: - f_info = fields_info[col] - relative_path = TableModeManager.__get_relative_path(f_info["path"], table_type) - return TableModeManager.__get_value( - relative_path, - data, - f_info["default_value"], - ) - - if table_type == TableTemplateType.AREA: - return { - area_id: columns_model.construct( - **{col: get_column_value(col, data) for col in columns} - ) # type: ignore - for area_id, data in glob_object.items() + area_manager: AreaManager, + link_manager: LinkManager, + thermal_manager: ThermalManager, + renewable_manager: RenewableManager, + st_storage_manager: STStorageManager, + binding_constraint_manager: BindingConstraintManager, + ) -> None: + self._area_manager = area_manager + self._link_manager = link_manager + self._thermal_manager = thermal_manager + self._renewable_manager = renewable_manager + self._st_storage_manager = st_storage_manager + self._binding_constraint_manager = binding_constraint_manager + + def _get_table_data_unsafe(self, study: RawStudy, table_type: TableModeType) -> TableDataDTO: + if table_type == TableModeType.AREA: + areas_map = self._area_manager.get_all_area_props(study) + data = {area_id: area.dict(by_alias=True) for area_id, area in areas_map.items()} + elif table_type == TableModeType.LINK: + links_map = self._link_manager.get_all_links_props(study) + data = { + f"{area1_id} / {area2_id}": link.dict(by_alias=True) for (area1_id, area2_id), link in links_map.items() } - - if table_type == TableTemplateType.BINDING_CONSTRAINT: - return { - data["id"]: columns_model.construct( - **{col: get_column_value(col, data) for col in columns} - ) # type: ignore - for data in glob_object.values() + elif table_type == TableModeType.THERMAL: + thermals_by_areas = self._thermal_manager.get_all_thermals_props(study) + data = { + f"{area_id} / {cluster_id}": cluster.dict(by_alias=True, exclude={"id", "name"}) + for area_id, thermals_by_ids in thermals_by_areas.items() + for cluster_id, cluster in thermals_by_ids.items() } + elif table_type == TableModeType.RENEWABLE: + renewables_by_areas = self._renewable_manager.get_all_renewables_props(study) + data = { + f"{area_id} / {cluster_id}": cluster.dict(by_alias=True, exclude={"id", "name"}) + for area_id, renewables_by_ids in renewables_by_areas.items() + for cluster_id, cluster in renewables_by_ids.items() + } + elif table_type == TableModeType.ST_STORAGE: + storages_by_areas = self._st_storage_manager.get_all_storages_props(study) + data = { + f"{area_id} / {cluster_id}": cluster.dict(by_alias=True, exclude={"id", "name"}) + for area_id, storages_by_ids in storages_by_areas.items() + for cluster_id, cluster in storages_by_ids.items() + } + elif table_type == TableModeType.BINDING_CONSTRAINT: + bc_seq = self._binding_constraint_manager.get_binding_constraints(study) + data = {bc.id: bc.dict(by_alias=True, exclude={"id", "name", "terms"}) for bc in bc_seq} + else: # pragma: no cover + raise NotImplementedError(f"Table type {table_type} not implemented") + return data - obj: Dict[str, Any] = {} - for id_1, value_1 in glob_object.items(): - for id_2, value_2 in value_1.items(): - obj[f"{id_1} / {id_2}"] = columns_model.construct( - **{col: get_column_value(col, value_2) for col in columns} - ) - - return obj - - def set_table_data( + def get_table_data( self, study: RawStudy, - table_type: TableTemplateType, - data: Dict[str, ColumnsModelTypes], - ) -> None: - commands: List[ICommand] = [] - bindings_by_id = None - command_context = self.storage_service.variant_study_service.command_factory.command_context - - for key, columns in data.items(): - path_vars = TableModeManager.__get_path_vars_from_key(table_type, key) - - if table_type == TableTemplateType.BINDING_CONSTRAINT: - file_study = self.storage_service.get_storage(study).get_raw(study) - bindings_by_id = bindings_by_id or { - binding["id"]: binding for binding in _get_glob_object(file_study, table_type).values() - } - binding_id = path_vars["id"] - current_binding = bindings_by_id.get(binding_id, None) - - if current_binding: - col_values = columns.dict(exclude_none=True) - current_binding_dto = BindingConstraintManager.process_constraint(current_binding) - - commands.append( - UpdateBindingConstraint( - id=binding_id, - enabled=col_values.get("enabled", current_binding_dto.enabled), - time_step=col_values.get("type", current_binding_dto.time_step), - operator=col_values.get("operator", current_binding_dto.operator), - coeffs=BindingConstraintManager.constraints_to_coeffs(current_binding_dto), - command_context=command_context, - ) - ) - else: - for col, val in columns.__iter__(): - if val is not None: - commands.append( - UpdateConfig( - target=TableModeManager.__get_column_path(table_type, path_vars, col), - data=val, - command_context=command_context, - ) - ) - - if commands: - file_study = self.storage_service.get_storage(study).get_raw(study) - execute_or_add_commands(study, file_study, commands, self.storage_service) - - @staticmethod - def __get_value(path: List[str], data: Dict[str, Any], default_value: Any) -> Any: - if len(path): - return TableModeManager.__get_value(path[1:], data.get(path[0], {}), default_value) - return data if data != {} else default_value - - @staticmethod - def __get_relative_path( - path: str, - table_type: TableTemplateType, - ) -> List[str]: - base_path = "" - path_arr = path.split("/") - - if table_type == TableTemplateType.AREA: - if path.startswith(THERMAL_PATH): - base_path = THERMAL_PATH - # Remove {area} - path_arr = path_arr[:-1] - else: - base_path = AREA_PATH - elif table_type == TableTemplateType.LINK: - base_path = LINK_PATH - elif table_type == TableTemplateType.CLUSTER: - base_path = CLUSTER_PATH - elif table_type == TableTemplateType.RENEWABLE: - base_path = RENEWABLE_PATH - elif table_type == TableTemplateType.BINDING_CONSTRAINT: - base_path = BINDING_CONSTRAINT_PATH - - return path_arr[len(base_path.split("/")) :] - - @staticmethod - def __get_column_path( - table_type: TableTemplateType, - path_vars: PathVars, - column: str, - ) -> str: - path = FIELDS_INFO_BY_TYPE[table_type][column]["path"] - - if table_type == TableTemplateType.AREA: - return path.format(area=path_vars["id"]) - if table_type == TableTemplateType.LINK: - return path.format(area1=path_vars["area1"], area2=path_vars["area2"]) - if table_type in [ - TableTemplateType.CLUSTER, - TableTemplateType.RENEWABLE, - ]: - return path.format(area=path_vars["area"], cluster=path_vars["cluster"]) - - return path - - @staticmethod - def __get_path_vars_from_key( - table_type: TableTemplateType, - key: str, - ) -> PathVars: - if table_type in [ - TableTemplateType.AREA, - TableTemplateType.BINDING_CONSTRAINT, - ]: - return PathVars(id=key) - if table_type == TableTemplateType.LINK: - area1, area2 = [v.strip() for v in key.split("/")] - return PathVars(area1=area1, area2=area2) - if table_type in [ - TableTemplateType.CLUSTER, - TableTemplateType.RENEWABLE, - ]: - area, cluster = [v.strip() for v in key.split("/")] - return PathVars(area=area, cluster=cluster) - - return PathVars() + table_type: TableModeType, + columns: t.Sequence[_TableColumn], + ) -> TableDataDTO: + """ + Get the table data of the specified type for the given study. + + Args: + study: The study to get the table data from. + table_type: The type of the table. + columns: The columns to include in the table. If empty, all columns are included. + + Returns: + The table data as a dictionary of dictionaries. + Where keys are the row names and values are dictionaries of column names and cell values. + """ + try: + data = self._get_table_data_unsafe(study, table_type) + except ChildNotFoundError: + # It's better to return an empty table than raising an 404 error + return {} + + df = pd.DataFrame.from_dict(data, orient="index") # type: ignore + if columns: + # Create a new dataframe with the listed columns. + df = pd.DataFrame(df, columns=columns) # type: ignore + + # According to the study version, some properties may not be present, + # so we need to drop columns that are all NaN. + df = df.dropna(axis=1, how="all") + + # Convert NaN to `None` because it is not JSON-serializable + df.replace(np.nan, None, inplace=True) + + return t.cast(TableDataDTO, df.to_dict(orient="index")) + + def update_table_data( + self, + study: RawStudy, + table_type: TableModeType, + data: TableDataDTO, + ) -> TableDataDTO: + """ + Update the properties of the objects in the study using the provided data. + + Args: + study: The study to update the objects in. + table_type: The type of the table. + data: The new properties of the objects as a dictionary of dictionaries. + Where keys are the row names and values are dictionaries of column names and cell values. + + Returns: + The updated properties of the objects including the old ones. + """ + if table_type == TableModeType.AREA: + # Use AreaOutput to update properties of areas, which may include `None` values + area_props_by_ids = {key: AreaOutput(**values) for key, values in data.items()} + areas_map = self._area_manager.update_areas_props(study, area_props_by_ids) + data = {area_id: area.dict(by_alias=True, exclude_none=True) for area_id, area in areas_map.items()} + return data + elif table_type == TableModeType.LINK: + links_map = {tuple(key.split(" / ")): LinkOutput(**values) for key, values in data.items()} + updated_map = self._link_manager.update_links_props(study, links_map) # type: ignore + data = { + f"{area1_id} / {area2_id}": link.dict(by_alias=True) + for (area1_id, area2_id), link in updated_map.items() + } + return data + elif table_type == TableModeType.THERMAL: + thermals_by_areas: t.MutableMapping[str, t.MutableMapping[str, ThermalClusterInput]] + thermals_by_areas = collections.defaultdict(dict) + for key, values in data.items(): + area_id, cluster_id = key.split(" / ") + thermals_by_areas[area_id][cluster_id] = ThermalClusterInput(**values) + thermals_map = self._thermal_manager.update_thermals_props(study, thermals_by_areas) + data = { + f"{area_id} / {cluster_id}": cluster.dict(by_alias=True, exclude={"id", "name"}) + for area_id, thermals_by_ids in thermals_map.items() + for cluster_id, cluster in thermals_by_ids.items() + } + return data + elif table_type == TableModeType.RENEWABLE: + renewables_by_areas: t.MutableMapping[str, t.MutableMapping[str, RenewableClusterInput]] + renewables_by_areas = collections.defaultdict(dict) + for key, values in data.items(): + area_id, cluster_id = key.split(" / ") + renewables_by_areas[area_id][cluster_id] = RenewableClusterInput(**values) + renewables_map = self._renewable_manager.update_renewables_props(study, renewables_by_areas) + data = { + f"{area_id} / {cluster_id}": cluster.dict(by_alias=True, exclude={"id", "name"}) + for area_id, renewables_by_ids in renewables_map.items() + for cluster_id, cluster in renewables_by_ids.items() + } + return data + elif table_type == TableModeType.ST_STORAGE: + storages_by_areas: t.MutableMapping[str, t.MutableMapping[str, STStorageInput]] + storages_by_areas = collections.defaultdict(dict) + for key, values in data.items(): + area_id, cluster_id = key.split(" / ") + storages_by_areas[area_id][cluster_id] = STStorageInput(**values) + storages_map = self._st_storage_manager.update_storages_props(study, storages_by_areas) + data = { + f"{area_id} / {cluster_id}": cluster.dict(by_alias=True, exclude={"id", "name"}) + for area_id, storages_by_ids in storages_map.items() + for cluster_id, cluster in storages_by_ids.items() + } + return data + elif table_type == TableModeType.BINDING_CONSTRAINT: + bcs_by_ids = {key: ConstraintInput(**values) for key, values in data.items()} + bcs_map = self._binding_constraint_manager.update_binding_constraints(study, bcs_by_ids) + return {bc_id: bc.dict(by_alias=True, exclude={"id", "name", "terms"}) for bc_id, bc in bcs_map.items()} + else: # pragma: no cover + raise NotImplementedError(f"Table type {table_type} not implemented") + + def get_table_schema(self, table_type: TableModeType) -> JSON: + """ + Get the properties of the table columns which type is provided as a parameter. + + Args: + table_type: The type of the table. + + Returns: + JSON Schema which allows to know the name, title and type of each column. + """ + if table_type == TableModeType.AREA: + return self._area_manager.get_table_schema() + elif table_type == TableModeType.LINK: + return self._link_manager.get_table_schema() + elif table_type == TableModeType.THERMAL: + return self._thermal_manager.get_table_schema() + elif table_type == TableModeType.RENEWABLE: + return self._renewable_manager.get_table_schema() + elif table_type == TableModeType.ST_STORAGE: + return self._st_storage_manager.get_table_schema() + elif table_type == TableModeType.BINDING_CONSTRAINT: + return self._binding_constraint_manager.get_table_schema() + else: # pragma: no cover + raise NotImplementedError(f"Table type {table_type} not implemented") diff --git a/antarest/study/business/thematic_trimming_field_infos.py b/antarest/study/business/thematic_trimming_field_infos.py index 764c2c9590..3baabd8014 100644 --- a/antarest/study/business/thematic_trimming_field_infos.py +++ b/antarest/study/business/thematic_trimming_field_infos.py @@ -4,7 +4,8 @@ import typing as t -from antarest.study.business.utils import AllOptionalMetaclass, FormFieldsBaseModel +from antarest.study.business.all_optional_meta import AllOptionalMetaclass +from antarest.study.business.utils import FormFieldsBaseModel class ThematicTrimmingFormFields(FormFieldsBaseModel, metaclass=AllOptionalMetaclass, use_none=True): diff --git a/antarest/study/business/timeseries_config_management.py b/antarest/study/business/timeseries_config_management.py index fac397b3be..418921e7f0 100644 --- a/antarest/study/business/timeseries_config_management.py +++ b/antarest/study/business/timeseries_config_management.py @@ -6,7 +6,7 @@ from antarest.study.business.enum_ignore_case import EnumIgnoreCase from antarest.study.business.utils import GENERAL_DATA_PATH, FormFieldsBaseModel, execute_or_add_commands from antarest.study.model import Study -from antarest.study.storage.rawstudy.model.filesystem.config.model import ENR_MODELLING +from antarest.study.storage.rawstudy.model.filesystem.config.model import EnrModelling from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy from antarest.study.storage.storage_service import StudyStorageService from antarest.study.storage.variantstudy.model.command.update_config import UpdateConfig @@ -193,7 +193,7 @@ def __get_form_fields_for_type( input_ = general_data.get("input", {}) output = general_data.get("output", {}) - is_aggregated = file_study.config.enr_modelling == ENR_MODELLING.AGGREGATED.value + is_aggregated = file_study.config.enr_modelling == EnrModelling.AGGREGATED.value if ts_type == TSType.RENEWABLES and is_aggregated: return None diff --git a/antarest/study/business/utils.py b/antarest/study/business/utils.py index 53596bf797..8c4b567b22 100644 --- a/antarest/study/business/utils.py +++ b/antarest/study/business/utils.py @@ -1,7 +1,5 @@ import typing as t -import pydantic.fields -import pydantic.main from pydantic import BaseModel from antarest.core.exceptions import CommandApplicationError @@ -82,90 +80,3 @@ class FieldInfo(t.TypedDict, total=False): encode: t.Optional[t.Callable[[t.Any], t.Any]] # (encoded_value, current_value) -> decoded_value decode: t.Optional[t.Callable[[t.Any, t.Optional[t.Any]], t.Any]] - - -class AllOptionalMetaclass(pydantic.main.ModelMetaclass): - """ - Metaclass that makes all fields of a Pydantic model optional. - - Usage: - class MyModel(BaseModel, metaclass=AllOptionalMetaclass): - field1: str - field2: int - ... - - Instances of the model can be created even if not all fields are provided during initialization. - Default values, when provided, are used unless `use_none` is set to `True`. - """ - - def __new__( - cls: t.Type["AllOptionalMetaclass"], - name: str, - bases: t.Tuple[t.Type[t.Any], ...], - namespaces: t.Dict[str, t.Any], - use_none: bool = False, - **kwargs: t.Dict[str, t.Any], - ) -> t.Any: - """ - Create a new instance of the metaclass. - - Args: - name: Name of the class to create. - bases: Base classes of the class to create (a Pydantic model). - namespaces: namespace of the class to create that defines the fields of the model. - use_none: If `True`, the default value of the fields is set to `None`. - Note that this field is not part of the Pydantic model, but it is an extension. - **kwargs: Additional keyword arguments used by the metaclass. - """ - # Modify the annotations of the class (but not of the ancestor classes) - # in order to make all fields optional. - # If the current model inherits from another model, the annotations of the ancestor models - # are not modified, because the fields are already converted to `ModelField`. - annotations = namespaces.get("__annotations__", {}) - for field_name, field_type in annotations.items(): - if not field_name.startswith("__"): - # Making already optional fields optional is not a problem (nothing is changed). - annotations[field_name] = t.Optional[field_type] - namespaces["__annotations__"] = annotations - - if use_none: - # Modify the namespace fields to set their default value to `None`. - for field_name, field_info in namespaces.items(): - if isinstance(field_info, pydantic.fields.FieldInfo): - field_info.default = None - field_info.default_factory = None - - # Create the class: all annotations are converted into `ModelField`. - instance = super().__new__(cls, name, bases, namespaces, **kwargs) - - # Modify the inherited fields of the class to make them optional - # and set their default value to `None`. - model_field: pydantic.fields.ModelField - for field_name, model_field in instance.__fields__.items(): - model_field.required = False - model_field.allow_none = True - if use_none: - model_field.default = None - model_field.default_factory = None - model_field.field_info.default = None - - return instance - - -MODEL = t.TypeVar("MODEL", bound=t.Type[BaseModel]) - - -def camel_case_model(model: MODEL) -> MODEL: - """ - This decorator can be used to modify a model to use camel case aliases. - - Args: - model: The pydantic model to modify. - - Returns: - The modified model. - """ - model.__config__.alias_generator = to_camel_case - for field_name, field in model.__fields__.items(): - field.alias = to_camel_case(field_name) - return model diff --git a/antarest/study/business/xpansion_management.py b/antarest/study/business/xpansion_management.py index f3adadad32..22c612af9a 100644 --- a/antarest/study/business/xpansion_management.py +++ b/antarest/study/business/xpansion_management.py @@ -11,8 +11,8 @@ from antarest.core.exceptions import BadZipBinary from antarest.core.model import JSON +from antarest.study.business.all_optional_meta import AllOptionalMetaclass from antarest.study.business.enum_ignore_case import EnumIgnoreCase -from antarest.study.business.utils import AllOptionalMetaclass from antarest.study.model import Study from antarest.study.storage.rawstudy.model.filesystem.bucket_node import BucketNode from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy @@ -365,7 +365,7 @@ def get_xpansion_settings(self, study: Study) -> GetXpansionSettings: logger.info(f"Getting xpansion settings for study '{study.id}'") file_study = self.study_storage_service.get_storage(study).get_raw(study) config_obj = file_study.tree.get(["user", "expansion", "settings"]) - with contextlib.suppress(KeyError): + with contextlib.suppress(ChildNotFoundError): config_obj["sensitivity_config"] = file_study.tree.get( ["user", "expansion", "sensitivity", "sensitivity_in"] ) diff --git a/antarest/study/common/default_values.py b/antarest/study/common/default_values.py index cab69d477d..be2eda1111 100644 --- a/antarest/study/common/default_values.py +++ b/antarest/study/common/default_values.py @@ -1,3 +1,6 @@ +from enum import Enum + + class FilteringOptions: FILTER_SYNTHESIS: str = "hourly, daily, weekly, monthly, annual" FILTER_YEAR_BY_YEAR: str = "hourly, daily, weekly, monthly, annual" @@ -25,3 +28,15 @@ class LinkProperties: COLORR: int = 112 COLORG: int = 112 COLORB: int = 112 + + +class AreasQueryFile(str, Enum): + VALUES = "values" + DETAILS = "details" + DETAILS_ST_STORAGE = "details-st-storage" + DETAILS_RES = "details-res" + + +class LinksQueryFile(str, Enum): + VALUES = "values" + DETAILS = "details" diff --git a/antarest/study/common/studystorage.py b/antarest/study/common/studystorage.py index c6a271a66f..e10b44a48c 100644 --- a/antarest/study/common/studystorage.py +++ b/antarest/study/common/studystorage.py @@ -1,18 +1,20 @@ +import typing as t from abc import ABC, abstractmethod from pathlib import Path -from typing import BinaryIO, Generic, List, Optional, Sequence, TypeVar, Union from antarest.core.exceptions import StudyNotFoundError from antarest.core.model import JSON from antarest.core.requests import RequestParameters +from antarest.study.common.default_values import AreasQueryFile, LinksQueryFile from antarest.study.model import Study, StudyMetadataDTO, StudyMetadataPatchDTO, StudySimResultDTO from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfigDTO from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy +from antarest.study.storage.rawstudy.model.filesystem.matrix.matrix import MatrixFrequency -T = TypeVar("T", bound=Study) +T = t.TypeVar("T", bound=Study) -class IStudyStorageService(ABC, Generic[T]): +class IStudyStorageService(ABC, t.Generic[T]): @abstractmethod def create(self, metadata: T) -> T: """ @@ -23,7 +25,6 @@ def create(self, metadata: T) -> T: Returns: new study information """ - raise NotImplementedError() @abstractmethod def get( @@ -44,7 +45,58 @@ def get( Returns: study data formatted in json """ - raise NotImplementedError() + + @abstractmethod + def aggregate_areas_data( + self, + metadata: T, + output_id: str, + query_file: AreasQueryFile, + frequency: MatrixFrequency, + mc_years: t.Sequence[int], + areas_ids: t.Sequence[str], + columns_names: t.Sequence[str], + ) -> t.Dict[str, t.Any]: + """ + Entry point to fetch areas data inside study's output. + + Args: + metadata: study for which we want to perform the aggregation + output_id: simulation ID + query_file: "values", "details", "details-st-storage", "details-res" + frequency: "hourly", "daily", "weekly", "monthly", "annual" + mc_years: list of Monte Carlo years to consider, if empty, all years are considered + areas_ids: list of areas to consider, if empty, all areas are considered + columns_names: list of columns to consider, if empty, all columns are considered + + Returns: the areas aggregated data in a JSON format + + """ + + @abstractmethod + def aggregate_links_data( + self, + metadata: T, + output_id: str, + query_file: LinksQueryFile, + frequency: MatrixFrequency, + mc_years: t.Sequence[int], + columns_names: t.Sequence[str], + ) -> t.Dict[str, t.Any]: + """ + Entry point to fetch links raw data inside study's output. + + Args: + metadata: study for which we want to perform the aggregation + output_id: simulation ID + query_file: "values", "details" + frequency: "hourly", "daily", "weekly", "monthly", "annual" + mc_years: list of Monte Carlo years to consider, if empty, all years are considered + columns_names: list of columns to consider, if empty, all columns are considered + + Returns: the links aggregated data in a JSON format + + """ @abstractmethod def exists(self, metadata: T) -> bool: @@ -56,10 +108,9 @@ def exists(self, metadata: T) -> bool: Returns: true if study presents in disk, false else. """ - raise NotImplementedError() @abstractmethod - def copy(self, src_meta: T, dest_name: str, groups: Sequence[str], with_outputs: bool = False) -> T: + def copy(self, src_meta: T, dest_name: str, groups: t.Sequence[str], with_outputs: bool = False) -> T: """ Create a new study by copying a reference study. @@ -72,7 +123,6 @@ def copy(self, src_meta: T, dest_name: str, groups: Sequence[str], with_outputs: Returns: The newly created study. """ - raise NotImplementedError() @abstractmethod def patch_update_study_metadata(self, study: T, metadata: StudyMetadataPatchDTO) -> StudyMetadataDTO: @@ -85,15 +135,14 @@ def patch_update_study_metadata(self, study: T, metadata: StudyMetadataPatchDTO) Returns: study metadata """ - raise NotImplementedError() @abstractmethod def import_output( self, study: T, - output: Union[BinaryIO, Path], - output_name: Optional[str] = None, - ) -> Optional[str]: + output: t.Union[t.BinaryIO, Path], + output_name: t.Optional[str] = None, + ) -> t.Optional[str]: """ Import an output Args: @@ -102,18 +151,17 @@ def import_output( output_name: Optional name suffix to append to the output name Returns: None """ - raise NotImplementedError() @abstractmethod def get_study_information(self, metadata: T) -> StudyMetadataDTO: - raise NotImplementedError() + """Get study information.""" @abstractmethod def get_raw( self, metadata: T, use_cache: bool = True, - output_dir: Optional[Path] = None, + output_dir: t.Optional[Path] = None, ) -> FileStudy: """ Fetch a study raw tree object and its config @@ -124,10 +172,9 @@ def get_raw( Returns: the config and study tree object """ - raise NotImplementedError() @abstractmethod - def get_study_sim_result(self, metadata: T) -> List[StudySimResultDTO]: + def get_study_sim_result(self, metadata: T) -> t.List[StudySimResultDTO]: """ Get global result information @@ -137,7 +184,6 @@ def get_study_sim_result(self, metadata: T) -> List[StudySimResultDTO]: Returns: study output data """ - raise NotImplementedError() @abstractmethod def set_reference_output(self, metadata: T, output_id: str, status: bool) -> None: @@ -149,7 +195,6 @@ def set_reference_output(self, metadata: T, output_id: str, status: bool) -> Non output_id: the id of output to set the reference status. status: true to set it as reference, false to unset it. """ - raise NotImplementedError() @abstractmethod def delete(self, metadata: T) -> None: @@ -161,7 +206,6 @@ def delete(self, metadata: T) -> None: Returns: """ - raise NotImplementedError() @abstractmethod def delete_output(self, metadata: T, output_id: str) -> None: @@ -174,7 +218,6 @@ def delete_output(self, metadata: T, output_id: str) -> None: Returns: """ - raise NotImplementedError() @abstractmethod def get_study_path(self, metadata: Study) -> Path: @@ -186,7 +229,6 @@ def get_study_path(self, metadata: Study) -> Path: Returns: study path """ - raise NotImplementedError() def _check_study_exists(self, metadata: Study) -> None: """ @@ -214,7 +256,6 @@ def export_study(self, metadata: T, target: Path, outputs: bool = True) -> Path: Returns: Path: The path to the created ZIP file containing the study files. """ - raise NotImplementedError() @abstractmethod def export_output(self, metadata: T, output_id: str, target: Path) -> None: @@ -228,7 +269,6 @@ def export_output(self, metadata: T, output_id: str, target: Path) -> None: Returns: zip file with study files compressed inside """ - raise NotImplementedError() @abstractmethod def export_study_flat( @@ -236,7 +276,7 @@ def export_study_flat( metadata: T, dst_path: Path, outputs: bool = True, - output_list_filter: Optional[List[str]] = None, + output_list_filter: t.Optional[t.List[str]] = None, denormalize: bool = True, ) -> None: """ @@ -249,10 +289,9 @@ def export_study_flat( output_list_filter: list of outputs to keep (None indicate all outputs). denormalize: denormalize the study (replace matrix links by real matrices). """ - raise NotImplementedError() @abstractmethod - def get_synthesis(self, metadata: T, params: Optional[RequestParameters] = None) -> FileStudyTreeConfigDTO: + def get_synthesis(self, metadata: T, params: t.Optional[RequestParameters] = None) -> FileStudyTreeConfigDTO: """ Return study synthesis Args: @@ -261,16 +300,16 @@ def get_synthesis(self, metadata: T, params: Optional[RequestParameters] = None) Returns: FileStudyTreeConfigDTO """ - raise NotImplementedError() @abstractmethod def initialize_additional_data(self, study: T) -> bool: - raise NotImplementedError() + """Initialize additional data for a study.""" @abstractmethod def archive_study_output(self, study: T, output_id: str) -> bool: - raise NotImplementedError() + """Archive a study output.""" + # noinspection SpellCheckingInspection @abstractmethod def unarchive_study_output(self, study: T, output_id: str, keep_src_zip: bool) -> bool: - raise NotImplementedError() + """Un-archive a study output.""" diff --git a/antarest/study/model.py b/antarest/study/model.py index fe993a1512..ad3d1f0fb4 100644 --- a/antarest/study/model.py +++ b/antarest/study/model.py @@ -6,7 +6,7 @@ from datetime import datetime, timedelta from pathlib import Path -from pydantic import BaseModel +from pydantic import BaseModel, validator from sqlalchemy import ( # type: ignore Boolean, Column, @@ -16,7 +16,6 @@ Integer, PrimaryKeyConstraint, String, - Table, ) from sqlalchemy.orm import relationship # type: ignore @@ -46,16 +45,37 @@ "840": "empty_study_840.zip", "850": "empty_study_850.zip", "860": "empty_study_860.zip", + "870": "empty_study_870.zip", + "880": "empty_study_880.zip", } -NEW_DEFAULT_STUDY_VERSION: str = "860" +NEW_DEFAULT_STUDY_VERSION: str = "880" -groups_metadata = Table( - "group_metadata", - Base.metadata, - Column("group_id", String(36), ForeignKey("groups.id")), - Column("study_id", String(36), ForeignKey("study.id")), -) + +class StudyGroup(Base): # type:ignore + """ + A table to manage the many-to-many relationship between `Study` and `Group` + + Attributes: + study_id: The ID of the study associated with the group. + group_id: The IS of the group associated with the study. + """ + + __tablename__ = "group_metadata" + __table_args__ = (PrimaryKeyConstraint("study_id", "group_id"),) + + group_id: str = Column(String(36), ForeignKey("groups.id", ondelete="CASCADE"), index=True, nullable=False) + study_id: str = Column(String(36), ForeignKey("study.id", ondelete="CASCADE"), index=True, nullable=False) + + def __str__(self) -> str: # pragma: no cover + cls_name = self.__class__.__name__ + return f"[{cls_name}] study_id={self.study_id}, group={self.group_id}" + + def __repr__(self) -> str: # pragma: no cover + cls_name = self.__class__.__name__ + study_id = self.study_id + group_id = self.group_id + return f"{cls_name}({study_id=}, {group_id=})" class StudyTag(Base): # type:ignore @@ -63,8 +83,8 @@ class StudyTag(Base): # type:ignore A table to manage the many-to-many relationship between `Study` and `Tag` Attributes: - study_id (str): The ID of the study associated with the tag. - tag_label (str): The label of the tag associated with the study. + study_id: The ID of the study associated with the tag. + tag_label: The label of the tag associated with the study. """ __tablename__ = "study_tag" @@ -74,7 +94,8 @@ class StudyTag(Base): # type:ignore tag_label: str = Column(String(40), ForeignKey("tag.label", ondelete="CASCADE"), index=True, nullable=False) def __str__(self) -> str: # pragma: no cover - return f"[StudyTag] study_id={self.study_id}, tag={self.tag}" + cls_name = self.__class__.__name__ + return f"[{cls_name}] study_id={self.study_id}, tag={self.tag}" def __repr__(self) -> str: # pragma: no cover cls_name = self.__class__.__name__ @@ -90,8 +111,8 @@ class Tag(Base): # type:ignore This class is used to store tags associated with studies. Attributes: - label (str): The label of the tag. - color (str): The color code associated with the tag. + label: The label of the tag. + color: The color code associated with the tag. """ __tablename__ = "tag" @@ -130,7 +151,7 @@ class StudyAdditionalData(Base): # type:ignore study_id = Column( String(36), - ForeignKey("study.id"), + ForeignKey("study.id", ondelete="CASCADE"), primary_key=True, ) author = Column(String(255), default="Unknown") @@ -174,7 +195,7 @@ class Study(Base): # type: ignore tags: t.List[Tag] = relationship(Tag, secondary=StudyTag.__table__, back_populates="studies") owner = relationship(Identity, uselist=False) - groups = relationship(Group, secondary=lambda: groups_metadata, cascade="") + groups = relationship(Group, secondary=StudyGroup.__table__, cascade="") additional_data = relationship( StudyAdditionalData, uselist=False, @@ -231,7 +252,7 @@ class RawStudy(Study): id = Column( String(36), - ForeignKey("study.id"), + ForeignKey("study.id", ondelete="CASCADE"), primary_key=True, ) content_status = Column(Enum(StudyContentStatus)) @@ -333,7 +354,18 @@ class StudyMetadataPatchDTO(BaseModel): scenario: t.Optional[str] = None status: t.Optional[str] = None doc: t.Optional[str] = None - tags: t.List[str] = [] + tags: t.Sequence[str] = () + + @validator("tags", each_item=True) + def _normalize_tags(cls, v: str) -> str: + """Remove leading and trailing whitespaces, and replace consecutive whitespaces by a single one.""" + tag = " ".join(v.split()) + if not tag: + raise ValueError("Tag cannot be empty") + elif len(tag) > 40: + raise ValueError(f"Tag is too long: {tag!r}") + else: + return tag class StudySimSettingsDTO(BaseModel): diff --git a/antarest/study/repository.py b/antarest/study/repository.py index 3aa6e60681..81c2463c69 100644 --- a/antarest/study/repository.py +++ b/antarest/study/repository.py @@ -3,10 +3,13 @@ import typing as t from pydantic import BaseModel, NonNegativeInt -from sqlalchemy import func, not_, or_ # type: ignore -from sqlalchemy.orm import Session, joinedload, with_polymorphic # type: ignore +from sqlalchemy import and_, func, not_, or_, sql # type: ignore +from sqlalchemy.orm import Query, Session, joinedload, with_polymorphic # type: ignore from antarest.core.interfaces.cache import ICache +from antarest.core.jwt import JWTUser +from antarest.core.model import PublicMode +from antarest.core.requests import RequestParameters from antarest.core.utils.fastapi_sqlalchemy import db from antarest.login.model import Group from antarest.study.model import DEFAULT_WORKSPACE_NAME, RawStudy, Study, StudyAdditionalData, Tag @@ -20,9 +23,7 @@ def escape_like(string: str, escape_char: str = "\\") -> str: from sqlalchemy_utils import escape_like - query = session.query(User).filter( - User.name.ilike(escape_like('John')) - ) + query = session.query(User).filter(User.name.ilike(escape_like("John"))) Args: string: a string to escape @@ -34,6 +35,43 @@ def escape_like(string: str, escape_char: str = "\\") -> str: return string.replace(escape_char, escape_char * 2).replace("%", escape_char + "%").replace("_", escape_char + "_") +class AccessPermissions(BaseModel, frozen=True, extra="forbid"): + """ + This class object is build to pass on the user identity and its associated groups information + into the listing function get_all below + """ + + is_admin: bool = False + user_id: t.Optional[int] = None + user_groups: t.Sequence[str] = () + + @classmethod + def from_params(cls, params: t.Union[RequestParameters, JWTUser]) -> "AccessPermissions": + """ + This function makes it easier to pass on user ids and groups into the repository filtering function by + extracting the associated `AccessPermissions` object. + + Args: + params: `RequestParameters` or `JWTUser` holding user ids and groups + + Returns: `AccessPermissions` + + """ + if isinstance(params, RequestParameters): + user = params.user + else: + user = params + + if user: + return cls( + is_admin=user.is_site_admin() or user.is_admin_token(), + user_id=user.id, + user_groups=[group.id for group in user.groups], + ) + else: + return cls() + + class StudyFilter(BaseModel, frozen=True, extra="forbid"): """Study filter class gathering the main filtering parameters @@ -50,6 +88,7 @@ class StudyFilter(BaseModel, frozen=True, extra="forbid"): exists: if raw study missing workspace: optional workspace of the study folder: optional folder prefix of the study + access_permissions: query user ID, groups and admins status """ name: str = "" @@ -64,6 +103,7 @@ class StudyFilter(BaseModel, frozen=True, extra="forbid"): exists: t.Optional[bool] = None workspace: str = "" folder: str = "" + access_permissions: AccessPermissions = AccessPermissions() class StudySortBy(str, enum.Enum): @@ -138,7 +178,7 @@ def save( def refresh(self, metadata: Study) -> None: self.session.refresh(metadata) - def get(self, id: str) -> t.Optional[Study]: + def get(self, study_id: str) -> t.Optional[Study]: """Get the study by ID or return `None` if not found in database.""" # todo: I think we should use a `entity = with_polymorphic(Study, "*")` # to make sure RawStudy and VariantStudy fields are also fetched. @@ -146,13 +186,11 @@ def get(self, id: str) -> t.Optional[Study]: # When we fetch a study, we also need to fetch the associated owner and groups # to check the permissions of the current user efficiently. study: Study = ( - # fmt: off self.session.query(Study) .options(joinedload(Study.owner)) .options(joinedload(Study.groups)) .options(joinedload(Study.tags)) - .get(id) - # fmt: on + .get(study_id) ) return study @@ -200,6 +238,71 @@ def get_all( # efficiently (see: `AbstractStorageService.get_study_information`) entity = with_polymorphic(Study, "*") + q = self._search_studies(study_filter) + + # sorting + if sort_by: + if sort_by == StudySortBy.DATE_DESC: + q = q.order_by(entity.created_at.desc()) + elif sort_by == StudySortBy.DATE_ASC: + q = q.order_by(entity.created_at.asc()) + elif sort_by == StudySortBy.NAME_DESC: + q = q.order_by(func.upper(entity.name).desc()) + elif sort_by == StudySortBy.NAME_ASC: + q = q.order_by(func.upper(entity.name).asc()) + else: + raise NotImplementedError(sort_by) + + # pagination + if pagination.page_nb or pagination.page_size: + limit = pagination.page_size + offset = pagination.page_nb * pagination.page_size + end = offset + limit + if sort_by is None: + q = q.order_by(entity.name.asc()) + if study_filter.groups or study_filter.tags: + studies: t.Sequence[Study] = q.all()[offset:end] + return studies + q = q.offset(offset).limit(limit) + + studies = q.all() + return studies + + def count_studies(self, study_filter: StudyFilter = StudyFilter()) -> int: + """ + Count all studies matching with specified filters. + + Args: + study_filter: composed of all filtering criteria. + + Returns: + Integer, corresponding to total number of studies matching with specified filters. + """ + q = self._search_studies(study_filter) + + total: int = q.count() + + return total + + def _search_studies( + self, + study_filter: StudyFilter, + ) -> Query: + """ + Build a `SQL Query` based on specified filters. + + Args: + study_filter: composed of all filtering criteria. + + Returns: + The `Query` corresponding to specified criteria (except for permissions). + """ + # When we fetch a study, we also need to fetch the associated owner and groups + # to check the permissions of the current user efficiently. + # We also need to fetch the additional data to display the study information + # efficiently (see: `AbstractStorageService.get_study_information`) + entity = with_polymorphic(Study, "*") + # noinspection PyTypeChecker q = self.session.query(entity) if study_filter.exists is not None: @@ -207,10 +310,12 @@ def get_all( q = q.filter(RawStudy.missing.is_(None)) else: q = q.filter(not_(RawStudy.missing.is_(None))) + q = q.options(joinedload(entity.owner)) q = q.options(joinedload(entity.groups)) - q = q.options(joinedload(entity.additional_data)) q = q.options(joinedload(entity.tags)) + q = q.options(joinedload(entity.additional_data)) + if study_filter.managed is not None: if study_filter.managed: q = q.filter(or_(entity.type == "variantstudy", RawStudy.workspace == DEFAULT_WORKSPACE_NAME)) @@ -218,13 +323,12 @@ def get_all( q = q.filter(entity.type == "rawstudy") q = q.filter(RawStudy.workspace != DEFAULT_WORKSPACE_NAME) if study_filter.study_ids: - q = q.filter(entity.id.in_(study_filter.study_ids)) + q = q.filter(entity.id.in_(study_filter.study_ids)) if study_filter.study_ids else q if study_filter.users: q = q.filter(entity.owner_id.in_(study_filter.users)) - if study_filter.groups: - q = q.join(entity.groups).filter(Group.id.in_(study_filter.groups)) if study_filter.tags: - q = q.join(entity.tags).filter(Tag.label.in_(study_filter.tags)) + upper_tags = [tag.upper() for tag in study_filter.tags] + q = q.join(entity.tags).filter(func.upper(Tag.label).in_(upper_tags)) if study_filter.archived is not None: q = q.filter(entity.archived == study_filter.archived) if study_filter.name: @@ -243,24 +347,27 @@ def get_all( if study_filter.versions: q = q.filter(entity.version.in_(study_filter.versions)) - if sort_by: - if sort_by == StudySortBy.DATE_DESC: - q = q.order_by(entity.created_at.desc()) - elif sort_by == StudySortBy.DATE_ASC: - q = q.order_by(entity.created_at.asc()) - elif sort_by == StudySortBy.NAME_DESC: - q = q.order_by(func.upper(entity.name).desc()) - elif sort_by == StudySortBy.NAME_ASC: - q = q.order_by(func.upper(entity.name).asc()) + # permissions + groups filtering + if not study_filter.access_permissions.is_admin and study_filter.access_permissions.user_id is not None: + condition_1 = entity.public_mode != PublicMode.NONE + condition_2 = entity.owner_id == study_filter.access_permissions.user_id + q1 = q.join(entity.groups).filter(Group.id.in_(study_filter.access_permissions.user_groups)) + if study_filter.groups: + q2 = q.join(entity.groups).filter(Group.id.in_(study_filter.groups)) + q2 = q1.intersect(q2) + q = q2.union( + q.join(entity.groups).filter(and_(or_(condition_1, condition_2), Group.id.in_(study_filter.groups))) + ) else: - raise NotImplementedError(sort_by) - - # pagination - if pagination.page_nb or pagination.page_size: - q = q.offset(pagination.page_nb * pagination.page_size).limit(pagination.page_size) + q = q1.union(q.filter(or_(condition_1, condition_2))) + elif not study_filter.access_permissions.is_admin and study_filter.access_permissions.user_id is None: + # return empty result + # noinspection PyTypeChecker + q = self.session.query(entity).filter(sql.false()) + elif study_filter.groups: + q = q.join(entity.groups).filter(Group.id.in_(study_filter.groups)) - studies: t.Sequence[Study] = q.all() - return studies + return q def get_all_raw(self, exists: t.Optional[bool] = None) -> t.Sequence[RawStudy]: query = self.session.query(RawStudy) @@ -272,23 +379,40 @@ def get_all_raw(self, exists: t.Optional[bool] = None) -> t.Sequence[RawStudy]: studies: t.Sequence[RawStudy] = query.all() return studies - def delete(self, id: str) -> None: + def delete(self, id_: str, *ids: str) -> None: + ids = (id_,) + ids session = self.session - u: Study = session.query(Study).get(id) - session.delete(u) + session.query(Study).filter(Study.id.in_(ids)).delete(synchronize_session=False) session.commit() def update_tags(self, study: Study, new_tags: t.Sequence[str]) -> None: """ Updates the tags associated with a given study in the database, - replacing existing tags with new ones. + replacing existing tags with new ones (case-insensitive). Args: study: The pre-existing study to be updated with the new tags. new_tags: The new tags to be associated with the input study in the database. """ - existing_tags = self.session.query(Tag).filter(Tag.label.in_(new_tags)).all() - new_labels = set(new_tags) - set([tag.label for tag in existing_tags]) - study.tags = [Tag(label=tag) for tag in new_labels] + existing_tags - self.session.merge(study) - self.session.commit() + new_upper_tags = {tag.upper(): tag for tag in new_tags} + session = self.session + existing_tags = session.query(Tag).filter(func.upper(Tag.label).in_(new_upper_tags)).all() + for tag in existing_tags: + if tag.label.upper() in new_upper_tags: + new_upper_tags.pop(tag.label.upper()) + study.tags = [Tag(label=tag) for tag in new_upper_tags.values()] + existing_tags + session.merge(study) + session.commit() + # Delete any tag that is not associated with any study. + # Note: If tags are to be associated with objects other than Study, this code must be updated. + session.query(Tag).filter(~Tag.studies.any()).delete(synchronize_session=False) # type: ignore + session.commit() + + def list_duplicates(self) -> t.List[t.Tuple[str, str]]: + """ + Get list of duplicates as tuples (id, path). + """ + session = self.session + subquery = session.query(Study.path).group_by(Study.path).having(func.count() > 1).subquery() + query = session.query(Study.id, Study.path).filter(Study.path.in_(subquery)) + return t.cast(t.List[t.Tuple[str, str]], query.all()) diff --git a/antarest/study/service.py b/antarest/study/service.py index 7954b4c5dc..66b3b2ddad 100644 --- a/antarest/study/service.py +++ b/antarest/study/service.py @@ -1,4 +1,5 @@ import base64 +import collections import contextlib import io import json @@ -12,6 +13,7 @@ from uuid import uuid4 import numpy as np +import pandas as pd from fastapi import HTTPException, UploadFile from markupsafe import escape from starlette.responses import FileResponse, Response @@ -20,6 +22,7 @@ from antarest.core.exceptions import ( BadEditInstructionException, CommandApplicationError, + IncorrectPathError, NotAManagedStudyException, StudyDeletionNotAllowed, StudyNotFoundError, @@ -46,7 +49,7 @@ from antarest.study.business.adequacy_patch_management import AdequacyPatchManager from antarest.study.business.advanced_parameters_management import AdvancedParamsManager from antarest.study.business.allocation_management import AllocationManager -from antarest.study.business.area_management import AreaCreationDTO, AreaInfoDTO, AreaManager, AreaType, AreaUI +from antarest.study.business.area_management import AreaCreationDTO, AreaInfoDTO, AreaManager, AreaType, UpdateAreaUi from antarest.study.business.areas.hydro_management import HydroManager from antarest.study.business.areas.properties_management import PropertiesManager from antarest.study.business.areas.renewable_management import RenewableManager @@ -54,6 +57,7 @@ from antarest.study.business.areas.thermal_management import ThermalManager from antarest.study.business.binding_constraint_management import BindingConstraintManager from antarest.study.business.config_management import ConfigManager +from antarest.study.business.correlation_management import CorrelationManager from antarest.study.business.district_manager import DistrictManager from antarest.study.business.general_management import GeneralManager from antarest.study.business.link_management import LinkInfoDTO, LinkManager @@ -71,6 +75,7 @@ XpansionCandidateDTO, XpansionManager, ) +from antarest.study.common.default_values import AreasQueryFile, LinksQueryFile from antarest.study.model import ( DEFAULT_WORKSPACE_NAME, NEW_DEFAULT_STUDY_VERSION, @@ -91,12 +96,21 @@ StudyMetadataPatchDTO, StudySimResultDTO, ) -from antarest.study.repository import StudyFilter, StudyMetadataRepository, StudyPagination, StudySortBy +from antarest.study.repository import ( + AccessPermissions, + StudyFilter, + StudyMetadataRepository, + StudyPagination, + StudySortBy, +) +from antarest.study.storage.matrix_profile import adjust_matrix_columns_index +from antarest.study.storage.rawstudy.model.filesystem.config.area import AreaUI from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfigDTO from antarest.study.storage.rawstudy.model.filesystem.folder_node import ChildNotFoundError from antarest.study.storage.rawstudy.model.filesystem.ini_file_node import IniFileNode from antarest.study.storage.rawstudy.model.filesystem.inode import INode from antarest.study.storage.rawstudy.model.filesystem.matrix.input_series_matrix import InputSeriesMatrix +from antarest.study.storage.rawstudy.model.filesystem.matrix.matrix import MatrixFrequency from antarest.study.storage.rawstudy.model.filesystem.matrix.output_series_matrix import OutputSeriesMatrix from antarest.study.storage.rawstudy.model.filesystem.raw_file_node import RawFileNode from antarest.study.storage.rawstudy.raw_study_service import RawStudyService @@ -262,12 +276,20 @@ def __init__( self.thermal_manager = ThermalManager(self.storage_service) self.st_storage_manager = STStorageManager(self.storage_service) self.ts_config_manager = TimeSeriesConfigManager(self.storage_service) - self.table_mode_manager = TableModeManager(self.storage_service) self.playlist_manager = PlaylistManager(self.storage_service) self.scenario_builder_manager = ScenarioBuilderManager(self.storage_service) self.xpansion_manager = XpansionManager(self.storage_service) self.matrix_manager = MatrixManager(self.storage_service) self.binding_constraint_manager = BindingConstraintManager(self.storage_service) + self.correlation_manager = CorrelationManager(self.storage_service) + self.table_mode_manager = TableModeManager( + self.areas, + self.links, + self.thermal_manager, + self.renewable_manager, + self.st_storage_manager, + self.binding_constraint_manager, + ) self.cache_service = cache_service self.config = config self.on_deletion_callbacks: t.List[t.Callable[[str], None]] = [] @@ -305,6 +327,72 @@ def get( return self.storage_service.get_storage(study).get(study, url, depth, formatted) + def aggregate_areas_data( + self, + uuid: str, + output_id: str, + query_file: AreasQueryFile, + frequency: MatrixFrequency, + mc_years: t.Sequence[int], + areas_ids: t.Sequence[str], + columns_names: t.Sequence[str], + params: RequestParameters, + ) -> JSON: + """ + Get study data inside filesystem + Args: + uuid: study uuid + output_id: simulation output ID + query_file: which types of data to retrieve ("values", "details", "details-st-storage", "details-res") + frequency: yearly, monthly, weekly, daily or hourly. + mc_years: list of monte-carlo years, if empty, all years are selected + areas_ids: list of areas names, if empty, all areas are selected + columns_names: columns to be selected, if empty, all columns are selected + params: request parameters + + Returns: data study formatted in json + + """ + study = self.get_study(uuid) + assert_permission(params.user, study, StudyPermissionType.READ) + output = self.storage_service.get_storage(study).aggregate_areas_data( + study, output_id, query_file, frequency, mc_years, areas_ids, columns_names + ) + + return output + + def aggregate_links_data( + self, + uuid: str, + output_id: str, + query_file: LinksQueryFile, + frequency: MatrixFrequency, + mc_years: t.Sequence[int], + columns_names: t.Sequence[str], + params: RequestParameters, + ) -> JSON: + """ + Get study data inside filesystem + Args: + uuid: study uuid + output_id: simulation output ID + query_file: which types of data to retrieve ("values", "details") + frequency: yearly, monthly, weekly, daily or hourly. + mc_years: list of monte-carlo years, if empty, all years are selected + columns_names: columns to be selected, if empty, all columns are selected + params: request parameters + + Returns: data study formatted in json + + """ + study = self.get_study(uuid) + assert_permission(params.user, study, StudyPermissionType.READ) + output = self.storage_service.get_storage(study).aggregate_links_data( + study, output_id, query_file, frequency, mc_years, columns_names + ) + + return output + def get_logs( self, study_id: str, @@ -435,7 +523,6 @@ def edit_comments( def get_studies_information( self, - params: RequestParameters, study_filter: StudyFilter, sort_by: t.Optional[StudySortBy] = None, pagination: StudyPagination = StudyPagination(), @@ -443,7 +530,6 @@ def get_studies_information( """ Get information for matching studies of a search query. Args: - params: request parameters study_filter: filtering parameters sort_by: how to sort the db query results pagination: set offset and limit for db query @@ -462,18 +548,23 @@ def get_studies_information( study_metadata = self._try_get_studies_information(study) if study_metadata is not None: studies[study_metadata.id] = study_metadata - return { - s.id: s - for s in filter( - lambda study_dto: assert_permission( - params.user, - study_dto, - StudyPermissionType.READ, - raising=False, - ), - studies.values(), - ) - } + return studies + + def count_studies( + self, + study_filter: StudyFilter, + ) -> int: + """ + Get number of matching studies. + Args: + study_filter: filtering parameters + + Returns: total number of studies matching the filtering criteria + """ + total: int = self.repository.count_studies( + study_filter=study_filter, + ) + return total def _try_get_studies_information(self, study: Study) -> t.Optional[StudyMetadataDTO]: try: @@ -692,20 +783,16 @@ def get_input_matrix_startdate( return get_start_date(file_study, output_id, level) def remove_duplicates(self) -> None: - study_paths: t.Dict[str, t.List[str]] = {} - for study in self.repository.get_all(): - if isinstance(study, RawStudy) and not study.archived: - path = str(study.path) - if path not in study_paths: - study_paths[path] = [] - study_paths[path].append(study.id) - - for studies_with_same_path in study_paths.values(): - if len(studies_with_same_path) > 1: - logger.info(f"Found studies {studies_with_same_path} with same path, de duplicating") - for study_name in studies_with_same_path[1:]: - logger.info(f"Removing study {study_name}") - self.repository.delete(study_name) + duplicates = self.repository.list_duplicates() + ids: t.List[str] = [] + # ids with same path + duplicates_by_path = collections.defaultdict(list) + for study_id, path in duplicates: + duplicates_by_path[path].append(study_id) + for path, study_ids in duplicates_by_path.items(): + ids.extend(study_ids[1:]) + if ids: # Check if ids is not empty + self.repository.delete(*ids) def sync_studies_on_disk(self, folders: t.List[StudyFolder], directory: t.Optional[Path] = None) -> None: """ @@ -1205,11 +1292,13 @@ def export_task(notifier: TaskUpdateNotifier) -> TaskResult: ) return FileResponse( tmp_export_file, - headers={"Content-Disposition": "inline"} - if filetype == ExportFormat.JSON - else { - "Content-Disposition": f'attachment; filename="output-{output_id}.{"tar.gz" if filetype == ExportFormat.TAR_GZ else "zip"}' - }, + headers=( + {"Content-Disposition": "inline"} + if filetype == ExportFormat.JSON + else { + "Content-Disposition": f'attachment; filename="output-{output_id}.{"tar.gz" if filetype == ExportFormat.TAR_GZ else "zip"}' + } + ), media_type=filetype, ) else: @@ -1775,7 +1864,7 @@ def update_area_ui( self, uuid: str, area_id: str, - area_ui: AreaUI, + area_ui: UpdateAreaUi, layer: str, params: RequestParameters, ) -> None: @@ -2133,10 +2222,24 @@ def update_matrix( raise BadEditInstructionException(str(exc)) from exc def check_and_update_all_study_versions_in_database(self, params: RequestParameters) -> None: + """ + This function updates studies version on the db. + + **Warnings: Only users with Admins rights should be able to run this function.** + + Args: + params: Request parameters holding user ID and groups + + Raises: + UserHasNotPermissionError: if params user is not admin. + + """ if params.user and not params.user.is_site_admin(): logger.error(f"User {params.user.id} is not site admin") raise UserHasNotPermissionError() - studies = self.repository.get_all(study_filter=StudyFilter(managed=False)) + studies = self.repository.get_all( + study_filter=StudyFilter(managed=False, access_permissions=AccessPermissions.from_params(params)) + ) for study in studies: storage = self.storage_service.raw_study_service @@ -2375,3 +2478,44 @@ def get_disk_usage(self, uuid: str, params: RequestParameters) -> int: study_path = self.storage_service.raw_study_service.get_study_path(study) # If the study is a variant, it's possible that it only exists in DB and not on disk. If so, we return 0. return get_disk_usage(study_path) if study_path.exists() else 0 + + def get_matrix_with_index_and_header( + self, *, study_id: str, path: str, with_index: bool, with_header: bool, parameters: RequestParameters + ) -> pd.DataFrame: + matrix_path = Path(path) + study = self.get_study(study_id) + + if matrix_path.parts in [("input", "hydro", "allocation"), ("input", "hydro", "correlation")]: + all_areas = t.cast( + t.List[AreaInfoDTO], + self.get_all_areas(study_id, area_type=AreaType.AREA, ui=False, params=parameters), + ) + if matrix_path.parts[-1] == "allocation": + hydro_matrix = self.allocation_manager.get_allocation_matrix(study, all_areas) + else: + hydro_matrix = self.correlation_manager.get_correlation_matrix(all_areas, study, []) # type: ignore + return pd.DataFrame(data=hydro_matrix.data, columns=hydro_matrix.columns, index=hydro_matrix.index) + + matrix_obj = self.get(study_id, path, depth=3, formatted=True, params=parameters) + if set(matrix_obj) != {"data", "index", "columns"}: + raise IncorrectPathError(f"The provided path does not point to a valid matrix: '{path}'") + if not matrix_obj["data"]: + return pd.DataFrame() + + df_matrix = pd.DataFrame(**matrix_obj) + if with_index: + matrix_index = self.get_input_matrix_startdate(study_id, path, parameters) + time_column = pd.date_range( + start=matrix_index.start_date, periods=len(df_matrix), freq=matrix_index.level.value[0] + ) + df_matrix.index = time_column + + adjust_matrix_columns_index( + df_matrix, + path, + with_index=with_index, + with_header=with_header, + study_version=int(study.version), + ) + + return df_matrix diff --git a/antarest/study/storage/abstract_storage_service.py b/antarest/study/storage/abstract_storage_service.py index af76bf533d..5a249ea011 100644 --- a/antarest/study/storage/abstract_storage_service.py +++ b/antarest/study/storage/abstract_storage_service.py @@ -2,17 +2,21 @@ import logging import shutil import tempfile +import typing as t from abc import ABC from pathlib import Path -from typing import BinaryIO, List, Optional, Union from uuid import uuid4 +import numpy as np +import pandas as pd + from antarest.core.config import Config from antarest.core.exceptions import BadOutputError, StudyOutputNotFoundError from antarest.core.interfaces.cache import CacheConstants, ICache from antarest.core.model import JSON, PublicMode from antarest.core.utils.utils import StopWatch, extract_zip, unzip, zip_dir from antarest.login.model import GroupDTO +from antarest.study.common.default_values import AreasQueryFile, LinksQueryFile from antarest.study.common.studystorage import IStudyStorageService, T from antarest.study.model import ( DEFAULT_WORKSPACE_NAME, @@ -30,11 +34,62 @@ from antarest.study.storage.rawstudy.model.filesystem.config.files import get_playlist from antarest.study.storage.rawstudy.model.filesystem.config.model import Simulation from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy, StudyFactory +from antarest.study.storage.rawstudy.model.filesystem.folder_node import ChildNotFoundError +from antarest.study.storage.rawstudy.model.filesystem.matrix.matrix import MatrixFrequency from antarest.study.storage.rawstudy.model.helpers import FileStudyHelpers from antarest.study.storage.utils import extract_output_name, fix_study_root, remove_from_cache logger = logging.getLogger(__name__) +TEMPLATE_PARTS = "output/{sim_id}/economy/mc-ind" +"""Template for the path to reach the output data.""" +HORIZON_TEMPLATE = "output/{sim_id}/about-the-study/parameters" +# noinspection SpellCheckingInspection +MCYEAR_COL = "mcYear" +"""Column name for the Monte Carlo year.""" +AREA_COL = "area" +"""Column name for the area.""" +LINK_COL = "link" +"""Column name for the link.""" +TIME_ID_COL = "timeId" +"""Column name for the time index.""" +TIME_COL = "time" +"""Column name for the timestamp.""" +MC_YEAR_INDEX = 0 +"""Index in path parts starting from the Monte Carlo year to determine the Monte Carlo year.""" +AREA_INDEX = 2 +"""Index in path parts starting from the Monte Carlo year to determine the area name.""" +LINK_END_1_INDEX = 2 +"""Index in path parts starting from the Monte Carlo year to determine the link first vertex.""" +LINK_END_2_INDEX = 3 +"""Index in path parts starting from the Monte Carlo year to determine the link second vertex.""" +QUERY_FILE_INDEX = -2 +"""Index in path parts starting from the Monte Carlo year to determine the if we fetch values, details etc .""" +FREQUENCY_INDEX = -2 +"""Index in path parts starting from the Monte Carlo year to determine matrix frequency.""" + + +def flatten_tree(path_tree: t.Dict[str, t.Any]) -> t.List[t.List[str]]: + """ + Flatten paths tree + Args: + path_tree: tree to flatten + + Returns: list of all tree paths parts flattened + + """ + + result = [] + + for key, value in path_tree.items(): + if isinstance(value, dict) and value: + result.extend([[key] + sub for sub in flatten_tree(value)]) + elif value: + result.append([key, value]) + else: + result.append([key]) + return result + class AbstractStorageService(IStudyStorageService[T], ABC): def __init__( @@ -85,7 +140,7 @@ def get_study_information( patch_metadata = patch.study or PatchStudy() study_workspace = getattr(study, "workspace", DEFAULT_WORKSPACE_NAME) - folder: Optional[str] = None + folder: t.Optional[str] = None if hasattr(study, "folder"): folder = study.folder @@ -142,7 +197,7 @@ def get( if url == "" and depth == -1: cache_id = f"{CacheConstants.RAW_STUDY}/{metadata.id}" - from_cache: Optional[JSON] = None + from_cache: t.Optional[JSON] = None if use_cache: from_cache = self.cache.get(cache_id) if from_cache is not None: @@ -157,10 +212,195 @@ def get( del study return data + def aggregate_areas_data( + self, + metadata: T, + output_id: str, + query_file: AreasQueryFile, + frequency: MatrixFrequency, + mc_years: t.Sequence[int], + areas_ids: t.Sequence[str], + columns_names: t.Sequence[str], + ) -> t.Dict[str, t.Any]: + """ + Entry point to fetch areas raw data. + Args: + metadata: study file + output_id: simulation ID + query_file: "values", "details", "details-st-storage", "details-res" + frequency: "hourly", "daily", "weekly", "monthly", "annual" + mc_years: list of Monte Carlo years to be selected (empty list means all) + areas_ids: list of areas names to be selected (empty list means all) + columns_names: list of columns names to be selected (empty list means all) + + Returns: JSON (DF like matrix) representing the aggregated areas data + + """ + study = self.get_raw(metadata) + # retrieve the horizon from the study output + parameters = study.tree.get(url=HORIZON_TEMPLATE.format(sim_id=output_id).split("/")) + horizon = parameters.get("general", {}).get("horizon", "Annual") + + # root parts to retrieve the data + parts = TEMPLATE_PARTS.format(sim_id=output_id).split("/") + mc_years_parts = flatten_tree(study.tree.get(parts, depth=1)) + # Monte Carlo years filtering + if mc_years: + mc_years_parts = [mc_year_parts for mc_year_parts in mc_years_parts if int(mc_year_parts[0]) in mc_years] + mc_years_parts = [mc_year_parts + ["areas"] for mc_year_parts in mc_years_parts] + full_areas_parts = [] + for mc_year_parts in mc_years_parts: + areas_parts = flatten_tree(study.tree.get(parts + mc_year_parts, depth=1)) + # Areas names filtering + if areas_ids: + areas_parts = [area_parts for area_parts in areas_parts if area_parts[0] in areas_ids] + full_areas_parts.extend([mc_year_parts + area_parts for area_parts in areas_parts]) + all_paths_parts = [] + for mc_year_area_parts in full_areas_parts: + files_parts = flatten_tree(study.tree.get(parts + mc_year_area_parts, depth=-1)) + all_paths_parts.extend([mc_year_area_parts + file_parts for file_parts in files_parts]) + # Frequency filtering + all_paths_parts = [path_parts for path_parts in all_paths_parts if frequency in path_parts[FREQUENCY_INDEX]] + # query file filtering + all_paths_parts = [path_parts for path_parts in all_paths_parts if query_file in path_parts[QUERY_FILE_INDEX]] + + final_df = pd.DataFrame() + for path_parts in all_paths_parts: + try: + node_data = study.tree.get(parts + path_parts[:-1]) + except ChildNotFoundError: + continue + + # normalize columns' names + node_data["columns"] = ( + [(col[0].upper()).strip() for col in node_data["columns"]] + if query_file == AreasQueryFile.VALUES + else [((" ".join(col)).upper()).strip() for col in node_data["columns"]] + ) + # create a DataFrame from the node data + df = pd.DataFrame(**node_data) + # columns filtering + if columns_names: + # noinspection PyTypeChecker + df = df[[col for col in df.columns if col in columns_names]] + + # rearrange columns order + new_column_order = df.columns.values.tolist() + new_column_order = [AREA_COL, MCYEAR_COL, TIME_ID_COL, TIME_COL] + new_column_order + + # add column for areas and one to record the Monte Carlo year + df[MCYEAR_COL] = [int(path_parts[MC_YEAR_INDEX])] * len(df) + df[AREA_COL] = [path_parts[AREA_INDEX]] * len(df) + # add a column for the time id + df[TIME_ID_COL] = list(range(1, len(df) + 1)) + # add horizon column + if frequency == MatrixFrequency.ANNUAL: + df[TIME_COL] = [horizon] * len(df) + else: + df[TIME_COL] = df.index + + # Reorganize the columns + df = df.reindex(columns=new_column_order) + + final_df = pd.concat([final_df, df], ignore_index=True) + + # replace np.nan by None + final_df = final_df.replace({np.nan: None}) + + return {str(k): v for k, v in final_df.to_dict(orient="split").items()} + + def aggregate_links_data( + self, + metadata: T, + output_id: str, + query_file: LinksQueryFile, + frequency: MatrixFrequency, + mc_years: t.Sequence[int], + columns_names: t.Sequence[str], + ) -> t.Dict[str, t.Any]: + """ + Entry point to fetch links raw data. + Args: + metadata: study file + output_id: simulation ID + query_file: "values", "details" + frequency: "hourly", "daily", "weekly", "monthly", "annual" + mc_years: list of Monte Carlo years to be selected (empty list means all) + columns_names: list of columns names to be selected (empty list means all) + + Returns: JSON (DF like matrix) representing the aggregated links data + + """ + study = self.get_raw(metadata) + # retrieve the horizon from the study output + parameters = study.tree.get(url=HORIZON_TEMPLATE.format(sim_id=output_id).split("/")) + horizon = parameters.get("general", {}).get("horizon", "Annual") + + # root parts to retrieve the data + parts = TEMPLATE_PARTS.format(sim_id=output_id).split("/") + mc_years_parts = flatten_tree(study.tree.get(parts, depth=1)) + # Monte Carlo years filtering + if mc_years: + mc_years_parts = [mc_year_parts for mc_year_parts in mc_years_parts if int(mc_year_parts[0]) in mc_years] + mc_years_parts = [mc_year_parts + ["links"] for mc_year_parts in mc_years_parts] + all_paths_parts = [] + for mc_year_parts in mc_years_parts: + files_parts = flatten_tree(study.tree.get(parts + mc_year_parts, depth=-1)) + all_paths_parts.extend([mc_year_parts + file_parts for file_parts in files_parts]) + # Frequency filtering + all_paths_parts = [path_parts for path_parts in all_paths_parts if frequency in path_parts[FREQUENCY_INDEX]] + # query file filtering + all_paths_parts = [path_parts for path_parts in all_paths_parts if query_file in path_parts[QUERY_FILE_INDEX]] + + final_df = pd.DataFrame() + for path_parts in all_paths_parts: + try: + node_data = study.tree.get(parts + path_parts[:-1]) + except ChildNotFoundError: + continue + + # normalize columns' names + node_data["columns"] = ( + [(col[0].upper()).strip() for col in node_data["columns"]] + if query_file == LinksQueryFile.VALUES + else [((" ".join(col)).upper()).strip() for col in node_data["columns"]] + ) + # create a DataFrame from the node data + df = pd.DataFrame(**node_data) + # columns filtering + if columns_names: + # noinspection PyTypeChecker + df = df[[col for col in df.columns if col in columns_names]] + + # rearrange columns order + new_column_order = df.columns.values.tolist() + new_column_order = [LINK_COL, MCYEAR_COL, TIME_ID_COL, TIME_COL] + new_column_order + + # add the Monte Carlo and link columns + df[MCYEAR_COL] = [int(path_parts[MC_YEAR_INDEX])] * len(df) + df[LINK_COL] = [path_parts[LINK_END_1_INDEX] + " - " + path_parts[LINK_END_2_INDEX]] * len(df) + # add a column for the time id + df[TIME_ID_COL] = list(range(1, len(df) + 1)) + # add horizon column + if frequency == MatrixFrequency.ANNUAL: + df[TIME_COL] = [horizon] * len(df) + else: + df[TIME_COL] = df.index + + # Reorganize the columns + df = df.reindex(columns=new_column_order) + + final_df = pd.concat([final_df, df], ignore_index=True) + + # replace np.nan by None + final_df = final_df.replace({np.nan: None}) + + return {str(k): v for k, v in final_df.to_dict(orient="split").items()} + def get_study_sim_result( self, study: T, - ) -> List[StudySimResultDTO]: + ) -> t.List[StudySimResultDTO]: """ Get global result information Args: @@ -169,7 +409,7 @@ def get_study_sim_result( """ study_data = self.get_raw(study) patch_metadata = self.patch_service.get(study) - results: List[StudySimResultDTO] = [] + results: t.List[StudySimResultDTO] = [] if study_data.config.outputs is not None: reference = (patch_metadata.outputs or PatchOutputs()).reference for output in study_data.config.outputs: @@ -209,9 +449,9 @@ def get_study_sim_result( def import_output( self, metadata: T, - output: Union[BinaryIO, Path], - output_name: Optional[str] = None, - ) -> Optional[str]: + output: t.Union[t.BinaryIO, Path], + output_name: t.Optional[str] = None, + ) -> t.Optional[str]: """ Import additional output in an existing study. @@ -229,7 +469,7 @@ def import_output( path_output = Path(metadata.path) / "output" / f"imported_output_{str(uuid4())}" study_id = metadata.id path_output.mkdir(parents=True) - output_full_name: Optional[str] + output_full_name: t.Optional[str] is_zipped = False stopwatch = StopWatch() try: diff --git a/antarest/study/storage/auto_archive_service.py b/antarest/study/storage/auto_archive_service.py index 911b715f2d..a1eafc40a3 100644 --- a/antarest/study/storage/auto_archive_service.py +++ b/antarest/study/storage/auto_archive_service.py @@ -10,7 +10,7 @@ from antarest.core.requests import RequestParameters from antarest.core.utils.fastapi_sqlalchemy import db from antarest.study.model import RawStudy, Study -from antarest.study.repository import StudyFilter +from antarest.study.repository import AccessPermissions, StudyFilter from antarest.study.service import StudyService from antarest.study.storage.variantstudy.model.dbmodel import VariantStudy @@ -28,7 +28,10 @@ def __init__(self, study_service: StudyService, config: Config): def _try_archive_studies(self) -> None: old_date = datetime.datetime.utcnow() - datetime.timedelta(days=self.config.storage.auto_archive_threshold_days) with db(): - studies: t.Sequence[Study] = self.study_service.repository.get_all(study_filter=StudyFilter(managed=True)) + # in this part full `Read` rights over studies are granted to this function + studies: t.Sequence[Study] = self.study_service.repository.get_all( + study_filter=StudyFilter(managed=True, access_permissions=AccessPermissions(is_admin=True)) + ) # list of study IDs and boolean indicating if it's a raw study (True) or a variant (False) study_ids_to_archive = [ (study.id, isinstance(study, RawStudy)) diff --git a/antarest/study/storage/matrix_profile.py b/antarest/study/storage/matrix_profile.py new file mode 100644 index 0000000000..7dc137dc10 --- /dev/null +++ b/antarest/study/storage/matrix_profile.py @@ -0,0 +1,211 @@ +import calendar +import copy +import fnmatch +import typing as t +from pathlib import Path + +import pandas as pd + + +class _MatrixProfile(t.NamedTuple): + """ + Matrix profile for time series or specific matrices. + """ + + cols: t.Sequence[str] + rows: t.Sequence[str] + + def process_dataframe( + self, + df: pd.DataFrame, + matrix_path: str, + *, + with_index: bool, + with_header: bool, + ) -> None: + """ + Adjust the column names and index of a dataframe according to the matrix profile. + + *NOTE:* The modification is done in place. + + Args: + df: The dataframe to process. + matrix_path: The path of the matrix file, relative to the study directory. + with_index: Whether to set the index of the dataframe. + with_header: Whether to set the column names of the dataframe. + """ + if with_header: + if Path(matrix_path).parts[1] == "links": + cols = self._process_links_columns(matrix_path) + else: + cols = self.cols + if cols: + df.columns = pd.Index(cols) + else: + df.columns = pd.Index([f"TS-{i}" for i in range(1, len(df.columns) + 1)]) + + if with_index and self.rows: + df.index = pd.Index(self.rows) + + def _process_links_columns(self, matrix_path: str) -> t.Sequence[str]: + """Process column names specific to the links matrices.""" + path_parts = Path(matrix_path).parts + area1_id = path_parts[2] + area2_id = path_parts[3] + result = list(self.cols) + for k, col in enumerate(result): + if col == "Hurdle costs direct": + result[k] = f"{col} ({area1_id}->{area2_id})" + elif col == "Hurdle costs indirect": + result[k] = f"{col} ({area2_id}->{area1_id})" + return result + + +_SPECIFIC_MATRICES: t.Dict[str, _MatrixProfile] +""" +The dictionary ``_SPECIFIC_MATRICES`` maps file patterns to ``_MatrixProfile`` objects, +representing non-time series matrices. +It's used in the `adjust_matrix_columns_index` method to fetch matrix profiles based on study versions. +""" + + +# noinspection SpellCheckingInspection +_SPECIFIC_MATRICES = { + "input/hydro/common/capacity/creditmodulations_*": _MatrixProfile( + cols=[str(i) for i in range(101)], + rows=["Generating Power", "Pumping Power"], + ), + "input/hydro/common/capacity/maxpower_*": _MatrixProfile( + cols=[ + "Generating Max Power (MW)", + "Generating Max Energy (Hours at Pmax)", + "Pumping Max Power (MW)", + "Pumping Max Energy (Hours at Pmax)", + ], + rows=[], + ), + "input/hydro/common/capacity/reservoir_*": _MatrixProfile( + # Values are displayed in % in the UI, but the actual values are in p.u. (per unit) + cols=["Lev Low (p.u)", "Lev Avg (p.u)", "Lev High (p.u)"], + rows=[], + ), + "input/hydro/common/capacity/waterValues_*": _MatrixProfile( + cols=[f"{i}%" for i in range(101)], + rows=[], + ), + "input/hydro/series/*/mod": _MatrixProfile(cols=[], rows=[]), + "input/hydro/series/*/ror": _MatrixProfile(cols=[], rows=[]), + "input/hydro/common/capacity/inflowPattern_*": _MatrixProfile(cols=["Inflow Pattern (X)"], rows=[]), + "input/hydro/prepro/*/energy": _MatrixProfile( + cols=["Expectation (MWh)", "Std Deviation (MWh)", "Min. (MWh)", "Max. (MWh)", "ROR Share"], + rows=calendar.month_name[1:], + ), + "input/thermal/prepro/*/*/modulation": _MatrixProfile( + cols=["Marginal cost modulation", "Market bid modulation", "Capacity modulation", "Min gen modulation"], + rows=[], + ), + "input/thermal/prepro/*/*/data": _MatrixProfile( + cols=["FO Duration", "PO Duration", "FO Rate", "PO Rate", "NPO Min", "NPO Max"], + rows=[], + ), + "input/reserves/*": _MatrixProfile( + cols=["Primary Res. (draft)", "Strategic Res. (draft)", "DSM", "Day Ahead"], + rows=[], + ), + "input/misc-gen/miscgen-*": _MatrixProfile( + cols=["CHP", "Bio Mass", "Bio Gaz", "Waste", "GeoThermal", "Other", "PSP", "ROW Balance"], + rows=[], + ), + "input/bindingconstraints/*": _MatrixProfile(cols=["<", ">", "="], rows=[]), + "input/links/*/*": _MatrixProfile( + cols=[ + "Capacités de transmission directes", + "Capacités de transmission indirectes", + "Hurdle costs direct", + "Hurdle costs indirect", + "Impedances", + "Loop flow", + "P.Shift Min", + "P.Shift Max", + ], + rows=[], + ), +} + +_SPECIFIC_MATRICES_820 = copy.deepcopy(_SPECIFIC_MATRICES) +"""Specific matrices for study version 8.2.""" + +_SPECIFIC_MATRICES_820["input/links/*/*"] = _MatrixProfile( + cols=[ + "Hurdle costs direct", + "Hurdle costs indirect", + "Impedances", + "Loop flow", + "P.Shift Min", + "P.Shift Max", + ], + rows=[], +) + +# Specific matrices for study version 8.6 +_SPECIFIC_MATRICES_860 = copy.deepcopy(_SPECIFIC_MATRICES_820) +"""Specific matrices for study version 8.6.""" + +# noinspection SpellCheckingInspection +# +_SPECIFIC_MATRICES_860["input/hydro/series/*/mingen"] = _MatrixProfile(cols=[], rows=[]) + +_SPECIFIC_MATRICES_870 = copy.deepcopy(_SPECIFIC_MATRICES_820) +"""Specific matrices for study version 8.7.""" + +# noinspection SpellCheckingInspection +# Scenarized RHS for binding constraints +_SPECIFIC_MATRICES_870["input/bindingconstraints/*"] = _MatrixProfile(cols=[], rows=[]) + + +def adjust_matrix_columns_index( + df: pd.DataFrame, matrix_path: str, with_index: bool, with_header: bool, study_version: int +) -> None: + """ + Adjust the column names and index of a dataframe according to the matrix profile. + + *NOTE:* The modification is done in place. + + Args: + df: The dataframe to process. + matrix_path: The path of the matrix file, relative to the study directory. + with_index: Whether to set the index of the dataframe. + with_header: Whether to set the column names of the dataframe. + study_version: The version of the study. + """ + # Get the matrix profiles for a given study version + if study_version < 820: + matrix_profiles = _SPECIFIC_MATRICES + elif study_version < 860: + matrix_profiles = _SPECIFIC_MATRICES_820 + elif study_version < 870: + matrix_profiles = _SPECIFIC_MATRICES_860 + else: + matrix_profiles = _SPECIFIC_MATRICES_870 + + # Apply the matrix profile to the dataframe to adjust the column names and index + for pattern, matrix_profile in matrix_profiles.items(): + if fnmatch.fnmatch(matrix_path, pattern): + matrix_profile.process_dataframe( + df, + matrix_path, + with_index=with_index, + with_header=with_header, + ) + return + + if fnmatch.fnmatch(matrix_path, "output/*"): + # Outputs already have their own column names + return + + # The matrix may be a time series, in which case we don't need to adjust anything + # (the "Time" columns is already the index) + # Column names should be Monte-Carlo years: "TS-1", "TS-2", ... + df.columns = pd.Index([f"TS-{i}" for i in range(1, len(df.columns) + 1)]) + + return None diff --git a/antarest/study/storage/rawstudy/ini_reader.py b/antarest/study/storage/rawstudy/ini_reader.py index f145b948a9..84be7c099b 100644 --- a/antarest/study/storage/rawstudy/ini_reader.py +++ b/antarest/study/storage/rawstudy/ini_reader.py @@ -109,7 +109,7 @@ def read(self, path: t.Any) -> JSON: sections = self._parse_ini_file(f) except FileNotFoundError: # If the file is missing, an empty dictionary is returned. - # This is required tp mimic the behavior of `configparser.ConfigParser`. + # This is required to mimic the behavior of `configparser.ConfigParser`. return {} elif hasattr(path, "read"): diff --git a/antarest/study/storage/rawstudy/ini_writer.py b/antarest/study/storage/rawstudy/ini_writer.py index 9b348f1b27..3a5c1198d6 100644 --- a/antarest/study/storage/rawstudy/ini_writer.py +++ b/antarest/study/storage/rawstudy/ini_writer.py @@ -27,7 +27,6 @@ def _write_line( # type:ignore self, section_name, key, value ) if value is not None or not self._allow_no_value: # type:ignore - # value = IniConfigParser.format_value(value) value = delimiter + str(value).replace("\n", "\n\t") else: value = "" diff --git a/antarest/study/storage/rawstudy/model/filesystem/bucket_node.py b/antarest/study/storage/rawstudy/model/filesystem/bucket_node.py index 3415edd1c3..6106326d2f 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/bucket_node.py +++ b/antarest/study/storage/rawstudy/model/filesystem/bucket_node.py @@ -1,4 +1,4 @@ -from typing import Any, Callable, Dict, List, Optional +import typing as t from antarest.core.model import JSON, SUB_JSON from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig @@ -12,7 +12,7 @@ class RegisteredFile: def __init__( self, key: str, - node: Optional[Callable[[ContextServer, FileStudyTreeConfig], INode[Any, Any, Any]]], + node: t.Optional[t.Callable[[ContextServer, FileStudyTreeConfig], INode[t.Any, t.Any, t.Any]]], filename: str = "", ): self.key = key @@ -29,42 +29,36 @@ def __init__( self, context: ContextServer, config: FileStudyTreeConfig, - registered_files: Optional[List[RegisteredFile]] = None, - default_file_node: Callable[..., INode[Any, Any, Any]] = RawFileNode, + registered_files: t.Optional[t.List[RegisteredFile]] = None, + default_file_node: t.Callable[..., INode[t.Any, t.Any, t.Any]] = RawFileNode, ): super().__init__(context, config) - self.registered_files: List[RegisteredFile] = registered_files or [] - self.default_file_node: Callable[..., INode[Any, Any, Any]] = default_file_node + self.registered_files: t.List[RegisteredFile] = registered_files or [] + self.default_file_node: t.Callable[..., INode[t.Any, t.Any, t.Any]] = default_file_node - def _get_registered_file(self, key: str) -> Optional[RegisteredFile]: - for registered_file in self.registered_files: - if registered_file.key == key: - return registered_file - return None + def _get_registered_file_by_key(self, key: str) -> t.Optional[RegisteredFile]: + return next((rf for rf in self.registered_files if rf.key == key), None) - def _get_registered_file_from_filename(self, filename: str) -> Optional[RegisteredFile]: - for registered_file in self.registered_files: - if registered_file.filename == filename: - return registered_file - return None + def _get_registered_file_by_filename(self, filename: str) -> t.Optional[RegisteredFile]: + return next((rf for rf in self.registered_files if rf.filename == filename), None) def save( self, data: SUB_JSON, - url: Optional[List[str]] = None, + url: t.Optional[t.List[str]] = None, ) -> None: self._assert_not_in_zipped_file() if not self.config.path.exists(): self.config.path.mkdir() - if url is None or len(url) == 0: - assert isinstance(data, Dict) + if not url: + assert isinstance(data, dict) for key, value in data.items(): self._save(value, key) else: key = url[0] if len(url) > 1: - registered_file = self._get_registered_file(key) + registered_file = self._get_registered_file_by_key(key) if registered_file: node = registered_file.node or self.default_file_node node(self.context, self.config.next_file(key)).save(data, url[1:]) @@ -74,7 +68,7 @@ def save( self._save(data, key) def _save(self, data: SUB_JSON, key: str) -> None: - registered_file = self._get_registered_file(key) + registered_file = self._get_registered_file_by_key(key) if registered_file: node, filename = ( registered_file.node or self.default_file_node, @@ -88,12 +82,12 @@ def _save(self, data: SUB_JSON, key: str) -> None: BucketNode(self.context, self.config.next_file(key)).save(data) def build(self) -> TREE: - if not self.config.path.exists(): - return dict() + if not self.config.path.is_dir(): + return {} children: TREE = {} for item in sorted(self.config.path.iterdir()): - registered_file = self._get_registered_file_from_filename(item.name) + registered_file = self._get_registered_file_by_filename(item.name) if registered_file: node = registered_file.node or self.default_file_node children[registered_file.key] = node(self.context, self.config.next_file(item.name)) @@ -107,7 +101,7 @@ def build(self) -> TREE: def check_errors( self, data: JSON, - url: Optional[List[str]] = None, + url: t.Optional[t.List[str]] = None, raising: bool = False, - ) -> List[str]: + ) -> t.List[str]: return [] diff --git a/antarest/study/storage/rawstudy/model/filesystem/common/area_matrix_list.py b/antarest/study/storage/rawstudy/model/filesystem/common/area_matrix_list.py index 1d39a72a66..0191b866d1 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/common/area_matrix_list.py +++ b/antarest/study/storage/rawstudy/model/filesystem/common/area_matrix_list.py @@ -1,4 +1,4 @@ -from typing import Any, Callable, Dict, Optional +import typing as t from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.context import ContextServer @@ -44,8 +44,8 @@ def __init__( config: FileStudyTreeConfig, *, prefix: str = "", - matrix_class: Callable[..., INode[Any, Any, Any]] = InputSeriesMatrix, - additional_matrix_params: Optional[Dict[str, Any]] = None, + matrix_class: t.Callable[..., INode[t.Any, t.Any, t.Any]] = InputSeriesMatrix, + additional_matrix_params: t.Optional[t.Dict[str, t.Any]] = None, ): super().__init__(context, config) self.prefix = prefix @@ -77,7 +77,7 @@ def __init__( context: ContextServer, config: FileStudyTreeConfig, area: str, - matrix_class: Callable[[ContextServer, FileStudyTreeConfig], INode[Any, Any, Any]], + matrix_class: t.Callable[[ContextServer, FileStudyTreeConfig], INode[t.Any, t.Any, t.Any]], ): super().__init__(context, config) self.area = area @@ -91,13 +91,31 @@ def build(self) -> TREE: return children +class BindingConstraintMatrixList(FolderNode): + def __init__( + self, + context: ContextServer, + config: FileStudyTreeConfig, + matrix_class: t.Callable[[ContextServer, FileStudyTreeConfig], INode[t.Any, t.Any, t.Any]], + ): + super().__init__(context, config) + self.matrix_class = matrix_class + + def build(self) -> TREE: + """Builds the folder structure and creates child nodes representing each matrix file.""" + return { + file.stem: self.matrix_class(self.context, self.config.next_file(file.name)) + for file in self.config.path.glob("*.txt") + } + + class ThermalMatrixList(FolderNode): def __init__( self, context: ContextServer, config: FileStudyTreeConfig, area: str, - matrix_class: Callable[[ContextServer, FileStudyTreeConfig], INode[Any, Any, Any]], + matrix_class: t.Callable[[ContextServer, FileStudyTreeConfig], INode[t.Any, t.Any, t.Any]], ): super().__init__(context, config) self.area = area @@ -119,19 +137,19 @@ def __init__( self, context: ContextServer, config: FileStudyTreeConfig, - klass: Callable[ + klass: t.Callable[ [ ContextServer, FileStudyTreeConfig, str, - Callable[ + t.Callable[ [ContextServer, FileStudyTreeConfig], - INode[Any, Any, Any], + INode[t.Any, t.Any, t.Any], ], ], - INode[Any, Any, Any], + INode[t.Any, t.Any, t.Any], ], - matrix_class: Callable[[ContextServer, FileStudyTreeConfig], INode[Any, Any, Any]], + matrix_class: t.Callable[[ContextServer, FileStudyTreeConfig], INode[t.Any, t.Any, t.Any]], ): super().__init__(context, config) self.klass = klass diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/area.py b/antarest/study/storage/rawstudy/model/filesystem/config/area.py new file mode 100644 index 0000000000..5ade25159f --- /dev/null +++ b/antarest/study/storage/rawstudy/model/filesystem/config/area.py @@ -0,0 +1,541 @@ +""" +Object model used to read and update area configuration. +""" + +import typing as t + +from pydantic import Field, root_validator, validator + +from antarest.study.business.enum_ignore_case import EnumIgnoreCase +from antarest.study.storage.rawstudy.model.filesystem.config.field_validators import ( + validate_color_rgb, + validate_colors, + validate_filtering, +) +from antarest.study.storage.rawstudy.model.filesystem.config.ini_properties import IniProperties + + +# noinspection SpellCheckingInspection +class OptimizationProperties(IniProperties): + """ + Object linked to `/input/areas//optimization.ini` information. + + Usage: + + >>> from antarest.study.storage.rawstudy.model.filesystem.config.area import OptimizationProperties + >>> from pprint import pprint + + Create and validate a new Optimization object from a dictionary read from a configuration file. + + >>> obj = { + ... "filtering": { + ... "filter-synthesis": "hourly, daily, weekly, monthly, annual", + ... "filter-year-by-year": "annual,hourly", + ... }, + ... "nodal optimization": { + ... "non-dispatchable-power": "true", + ... "dispatchable-hydro-power": "false", + ... "spread-unsupplied-energy-cost": "1500", + ... "spread-spilled-energy-cost": "317.2500", + ... }, + ... } + + >>> opt = OptimizationProperties(**obj) + + >>> pprint(opt.dict(by_alias=True), width=80) + {'filtering': {'filter-synthesis': 'hourly, daily, weekly, monthly, annual', + 'filter-year-by-year': 'hourly, annual'}, + 'nodal optimization': {'dispatchable-hydro-power': False, + 'non-dispatchable-power': True, + 'other-dispatchable-power': True, + 'spread-spilled-energy-cost': 317.25, + 'spread-unsupplied-energy-cost': 1500.0}} + + Update the filtering configuration : + + >>> opt.filtering.filter_synthesis = "hourly,weekly,monthly,annual,century" + >>> opt.filtering.filter_year_by_year = "hourly, monthly, annual" + + Update the modal optimization configuration : + + >>> opt.nodal_optimization.non_dispatchable_power = False + >>> opt.nodal_optimization.spread_spilled_energy_cost = 0.0 + + Convert the object to a dictionary for writing to a configuration file: + + >>> pprint(opt.dict(by_alias=True, exclude_defaults=True), width=80) + {'filtering': {'filter-synthesis': 'hourly, weekly, monthly, annual', + 'filter-year-by-year': 'hourly, monthly, annual'}, + 'nodal optimization': {'dispatchable-hydro-power': False, + 'non-dispatchable-power': False, + 'spread-unsupplied-energy-cost': 1500.0}} + """ + + class FilteringSection(IniProperties): + """Configuration read from section `[filtering]` of `/input/areas//optimization.ini`.""" + + filter_synthesis: str = Field("", alias="filter-synthesis") + filter_year_by_year: str = Field("", alias="filter-year-by-year") + + @validator("filter_synthesis", "filter_year_by_year", pre=True) + def _validate_filtering(cls, v: t.Any) -> str: + return validate_filtering(v) + + # noinspection SpellCheckingInspection + class ModalOptimizationSection(IniProperties): + """Configuration read from section `[nodal optimization]` of `/input/areas//optimization.ini`.""" + + non_dispatchable_power: bool = Field(default=True, alias="non-dispatchable-power") + dispatchable_hydro_power: bool = Field(default=True, alias="dispatchable-hydro-power") + other_dispatchable_power: bool = Field(default=True, alias="other-dispatchable-power") + spread_unsupplied_energy_cost: float = Field(default=0.0, ge=0, alias="spread-unsupplied-energy-cost") + spread_spilled_energy_cost: float = Field(default=0.0, ge=0, alias="spread-spilled-energy-cost") + + filtering: FilteringSection = Field( + default_factory=FilteringSection, + alias="filtering", + ) + nodal_optimization: ModalOptimizationSection = Field( + default_factory=ModalOptimizationSection, + alias="nodal optimization", + ) + + +class AdequacyPatchMode(EnumIgnoreCase): + """ + Adequacy patch mode. + + Only available if study version >= 830. + """ + + OUTSIDE = "outside" + INSIDE = "inside" + VIRTUAL = "virtual" + + +class AdequacyPathProperties(IniProperties): + """ + Object linked to `/input/areas//adequacy_patch.ini` information. + + Only available if study version >= 830. + """ + + class AdequacyPathSection(IniProperties): + """Configuration read from section `[adequacy-patch]` of `/input/areas//adequacy_patch.ini`.""" + + adequacy_patch_mode: AdequacyPatchMode = Field(default=AdequacyPatchMode.OUTSIDE, alias="adequacy-patch-mode") + + adequacy_patch: AdequacyPathSection = Field(default_factory=AdequacyPathSection, alias="adequacy-patch") + + +class AreaUI(IniProperties): + """ + Style of an area in the map or in a layer. + + Usage: + + >>> from antarest.study.storage.rawstudy.model.filesystem.config.area import AreaUI + >>> from pprint import pprint + + Create and validate a new AreaUI object from a dictionary read from a configuration file. + + >>> obj = { + ... "x": 1148, + ... "y": 144, + ... "color_r": 0, + ... "color_g": 128, + ... "color_b": 255, + ... } + >>> ui = AreaUI(**obj) + >>> pprint(ui.dict(by_alias=True), width=80) + {'colorRgb': '#0080FF', 'x': 1148, 'y': 144} + + Update the color: + + >>> ui.color_rgb = (192, 168, 127) + >>> pprint(ui.dict(by_alias=True), width=80) + {'colorRgb': '#C0A87F', 'x': 1148, 'y': 144} + """ + + x: int = Field(0, description="x coordinate of the area in the map") + y: int = Field(0, description="y coordinate of the area in the map") + color_rgb: str = Field( + "#E66C2C", + alias="colorRgb", + description="color of the area in the map", + ) + + @validator("color_rgb", pre=True) + def _validate_color_rgb(cls, v: t.Any) -> str: + return validate_color_rgb(v) + + @root_validator(pre=True) + def _validate_colors(cls, values: t.MutableMapping[str, t.Any]) -> t.Mapping[str, t.Any]: + return validate_colors(values) + + def to_config(self) -> t.Mapping[str, t.Any]: + """ + Convert the object to a dictionary for writing to a configuration file: + + Usage: + + >>> from antarest.study.storage.rawstudy.model.filesystem.config.area import AreaUI + >>> from pprint import pprint + + >>> ui = AreaUI(x=1148, y=144, color_rgb="#0080FF") + >>> pprint(ui.to_config(), width=80) + {'color_b': 255, 'color_g': 128, 'color_r': 0, 'x': 1148, 'y': 144} + """ + r = int(self.color_rgb[1:3], 16) + g = int(self.color_rgb[3:5], 16) + b = int(self.color_rgb[5:7], 16) + return {"x": self.x, "y": self.y, "color_r": r, "color_g": g, "color_b": b} + + +class UIProperties(IniProperties): + """ + Object linked to `/input/areas//ui.ini` information. + + Usage: + + >>> from antarest.study.storage.rawstudy.model.filesystem.config.area import UIProperties + >>> from pprint import pprint + + UIProperties has default values for `style` and `layers`: + + >>> ui = UIProperties() + >>> pprint(ui.dict(), width=80) + {'layer_styles': {0: {'color_rgb': '#E66C2C', 'x': 0, 'y': 0}}, + 'layers': {0}, + 'style': {'color_rgb': '#E66C2C', 'x': 0, 'y': 0}} + + Create and validate a new UI object from a dictionary read from a configuration file. + + >>> obj = { + ... "ui": { + ... "x": 1148, + ... "y": 144, + ... "color_r": 0, + ... "color_g": 128, + ... "color_b": 255, + ... "layers": "0 7", + ... }, + ... "layerX": {"0": 1148, "7": 18}, + ... "layerY": {"0": 144, "7": -22}, + ... "layerColor": { + ... "0": "0 , 128 , 255", + ... "4": "0 , 128 , 255", + ... "6": "192 , 168 , 99", + ... "7": "0 , 128 , 255", + ... "8": "0 , 128 , 255", + ... }, + ... } + + >>> ui = UIProperties(**obj) + >>> pprint(ui.dict(), width=80) + {'layer_styles': {0: {'color_rgb': '#0080FF', 'x': 1148, 'y': 144}, + 4: {'color_rgb': '#0080FF', 'x': 1148, 'y': 144}, + 6: {'color_rgb': '#C0A863', 'x': 1148, 'y': 144}, + 7: {'color_rgb': '#0080FF', 'x': 18, 'y': -22}, + 8: {'color_rgb': '#0080FF', 'x': 1148, 'y': 144}}, + 'layers': {0, 7}, + 'style': {'color_rgb': '#0080FF', 'x': 1148, 'y': 144}} + + """ + + style: AreaUI = Field( + default_factory=AreaUI, + description="style of the area in the map: coordinates and color", + ) + layers: t.Set[int] = Field( + default_factory=set, + description="layers where the area is visible", + ) + layer_styles: t.Dict[int, AreaUI] = Field( + default_factory=dict, + description="style of the area in each layer", + alias="layerStyles", + ) + + @root_validator(pre=True) + def _set_default_style(cls, values: t.MutableMapping[str, t.Any]) -> t.Mapping[str, t.Any]: + """Defined the default style if missing.""" + style = values.get("style") + if style is None: + values["style"] = AreaUI() + elif isinstance(style, dict): + values["style"] = AreaUI(**style) + else: + values["style"] = AreaUI(**style.dict()) + return values + + @root_validator(pre=True) + def _set_default_layers(cls, values: t.MutableMapping[str, t.Any]) -> t.Mapping[str, t.Any]: + """Define the default layers if missing.""" + _layers = values.get("layers") + if _layers is None: + values["layers"] = {0} + return values + + @root_validator(pre=True) + def _set_default_layer_styles(cls, values: t.MutableMapping[str, t.Any]) -> t.Mapping[str, t.Any]: + """Define the default layer styles if missing.""" + layer_styles = values.get("layer_styles") + if layer_styles is None: + values["layer_styles"] = {0: AreaUI()} + elif isinstance(layer_styles, dict): + values["layer_styles"] = {0: AreaUI()} + for key, style in layer_styles.items(): + key = int(key) + if isinstance(style, dict): + values["layer_styles"][key] = AreaUI(**style) + else: + values["layer_styles"][key] = AreaUI(**style.dict()) + else: + raise TypeError(f"Invalid type for layer_styles: {type(layer_styles)}") + return values + + @root_validator(pre=True) + def _validate_layers(cls, values: t.MutableMapping[str, t.Any]) -> t.Mapping[str, t.Any]: + # Parse the `[ui]` section (if any) + ui_section = values.pop("ui", {}) + if ui_section: + # If `layers` is a single integer, convert it to `str` first + layers = str(ui_section.pop("layers", "0")) + values["layers"] = set([int(layer) for layer in layers.split()]) + values["style"].x = ui_section.pop("x", values["style"].x) + values["style"].y = ui_section.pop("y", values["style"].y) + values["style"].color_rgb = ( + ui_section.pop("color_r", values["style"].color_rgb[0]), + ui_section.pop("color_g", values["style"].color_rgb[1]), + ui_section.pop("color_b", values["style"].color_rgb[2]), + ) + + # Parse the `[layerX]`, `[layerY]` and `[layerColor]` sections (if any) + layer_x_section = values.pop("layerX", {}) + layer_y_section = values.pop("layerY", {}) + layer_color_section = values.pop("layerColor", {}) + # Key are converted to `int` and values to `str` (for splitting) + layer_x_section = {int(layer): str(x) for layer, x in layer_x_section.items()} + layer_y_section = {int(layer): str(y) for layer, y in layer_y_section.items()} + layer_color_section = {int(layer): str(color) for layer, color in layer_color_section.items()} + # indexes must contain all the keys from the three sections + indexes = set(layer_x_section) | set(layer_y_section) | set(layer_color_section) + if indexes: + layer_styles = {index: values["style"].copy() for index in indexes} + for layer, x in layer_x_section.items(): + layer_styles[layer].x = int(x) + for layer, y in layer_y_section.items(): + layer_styles[layer].y = int(y) + for layer, color in layer_color_section.items(): + r, g, b = [int(c) for c in color.split(",")] + layer_styles[layer].color_rgb = r, g, b + values["layer_styles"].update(layer_styles) + values["layers"] = values["layers"].intersection(indexes) + + return values + + def to_config(self) -> t.Mapping[str, t.Mapping[str, t.Any]]: + """ + Convert the object to a dictionary for writing to a configuration file: + + Usage: + + >>> from antarest.study.storage.rawstudy.model.filesystem.config.area import UIProperties + >>> from pprint import pprint + + >>> ui = UIProperties( + ... style=AreaUI(x=1148, y=144, color_rgb=(0, 128, 255)), + ... layers={0, 7}, + ... layer_styles={ + ... 6: AreaUI(x=1148, y=144, color_rgb="#C0A863"), + ... 7: AreaUI(x=18, y=-22, color_rgb=(0, 128, 255)), + ... }, + ... ) + >>> pprint(ui.to_config(), width=80) + {'layerColor': {'0': '230, 108, 44', '6': '192, 168, 99', '7': '0, 128, 255'}, + 'layerX': {'0': 0, '6': 1148, '7': 18}, + 'layerY': {'0': 0, '6': 144, '7': -22}, + 'ui': {'color_b': 255, + 'color_g': 128, + 'color_r': 0, + 'layers': '0 7', + 'x': 1148, + 'y': 144}} + """ + obj: t.MutableMapping[str, t.MutableMapping[str, t.Any]] = { + "ui": {}, + "layerX": {}, + "layerY": {}, + "layerColor": {}, + } + obj["ui"].update(self.style.to_config()) + obj["ui"]["layers"] = " ".join(str(layer) for layer in sorted(self.layers)) + for layer, style in self.layer_styles.items(): + obj["layerX"][str(layer)] = style.x + obj["layerY"][str(layer)] = style.y + r = int(style.color_rgb[1:3], 16) + g = int(style.color_rgb[3:5], 16) + b = int(style.color_rgb[5:7], 16) + obj["layerColor"][str(layer)] = f"{r}, {g}, {b}" + return obj + + +class AreaFolder(IniProperties): + """ + Object linked to `/input/areas/` information. + + Usage: + + >>> from antarest.study.storage.rawstudy.model.filesystem.config.area import AreaFolder + >>> from pprint import pprint + + Create and validate a new AreaProperties object from a dictionary read from a configuration file. + + >>> obj = AreaFolder() + >>> pprint(obj.dict(), width=80) + {'adequacy_patch': None, + 'optimization': {'filtering': {'filter_synthesis': '', + 'filter_year_by_year': ''}, + 'nodal_optimization': {'dispatchable_hydro_power': True, + 'non_dispatchable_power': True, + 'other_dispatchable_power': True, + 'spread_spilled_energy_cost': 0.0, + 'spread_unsupplied_energy_cost': 0.0}}, + 'ui': {'layer_styles': {0: {'color_rgb': '#E66C2C', 'x': 0, 'y': 0}}, + 'layers': {0}, + 'style': {'color_rgb': '#E66C2C', 'x': 0, 'y': 0}}} + + >>> pprint(obj.to_config(), width=80) + {'optimization': {'filtering': {'filter-synthesis': '', + 'filter-year-by-year': ''}, + 'nodal optimization': {'dispatchable-hydro-power': True, + 'non-dispatchable-power': True, + 'other-dispatchable-power': True, + 'spread-spilled-energy-cost': 0.0, + 'spread-unsupplied-energy-cost': 0.0}}, + 'ui': {'layerColor': {'0': '230, 108, 44'}, + 'layerX': {'0': 0}, + 'layerY': {'0': 0}, + 'ui': {'color_b': 44, + 'color_g': 108, + 'color_r': 230, + 'layers': '0', + 'x': 0, + 'y': 0}}} + + We can construct an AreaProperties object from invalid data: + + >>> data = { + ... "optimization": { + ... "filtering": {"filter-synthesis": "annual, centennial"}, + ... "nodal optimization": { + ... "spread-spilled-energy-cost": "15.5", + ... "spread-unsupplied-energy-cost": "yes", + ... }, + ... }, + ... "ui": {"style": {"color_rgb": (0, 128, 256)}}, + ... } + + >>> obj = AreaFolder.construct(**data) + >>> pprint(obj.dict(), width=80) + {'adequacy_patch': None, + 'optimization': {'filtering': {'filter-synthesis': 'annual, centennial'}, + 'nodal optimization': {'spread-spilled-energy-cost': '15.5', + 'spread-unsupplied-energy-cost': 'yes'}}, + 'ui': {'style': {'color_rgb': (0, 128, 256)}}} + + >>> AreaFolder.validate(data) + Traceback (most recent call last): + ... + pydantic.error_wrappers.ValidationError: 1 validation error for AreaFolder + optimization -> nodal optimization -> spread-unsupplied-energy-cost + value is not a valid float (type=type_error.float) + """ + + optimization: OptimizationProperties = Field( + default_factory=OptimizationProperties, + description="optimization configuration", + ) + adequacy_patch: t.Optional[AdequacyPathProperties] = Field( + None, + description="adequacy patch configuration", + ) + ui: UIProperties = Field( + default_factory=UIProperties, + description="UI configuration", + ) + + +# noinspection SpellCheckingInspection +class ThermalAreasProperties(IniProperties): + """ + Object linked to `/input/thermal/areas.ini` information. + + Usage: + + >>> from antarest.study.storage.rawstudy.model.filesystem.config.area import ThermalAreasProperties + >>> from pprint import pprint + + Create and validate a new ThermalArea object from a dictionary read from a configuration file:: + + [unserverdenergycost] + at = 4000.80 + be = 3500 + de = 1250 + fr = 138.50 + + [spilledenergycost] + cz = 100.0 + + >>> obj = { + ... "unserverdenergycost": { + ... "at": "4000.80", + ... "be": "3500", + ... "de": "1250", + ... "fr": "138.50", + ... }, + ... "spilledenergycost": { + ... "cz": "100.0", + ... }, + ... } + >>> area = ThermalAreasProperties(**obj) + >>> pprint(area.dict(), width=80) + {'spilled_energy_cost': {'cz': 100.0}, + 'unserverd_energy_cost': {'at': 4000.8, + 'be': 3500.0, + 'de': 1250.0, + 'fr': 138.5}} + + Update the unserverd energy cost: + + >>> area.unserverd_energy_cost["at"] = 6500.0 + >>> area.unserverd_energy_cost["fr"] = 0.0 + >>> pprint(area.dict(), width=80) + {'spilled_energy_cost': {'cz': 100.0}, + 'unserverd_energy_cost': {'at': 6500.0, 'be': 3500.0, 'de': 1250.0, 'fr': 0.0}} + + Convert the object to a dictionary for writing to a configuration file: + + >>> pprint(area.to_config(), width=80) + {'spilledenergycost': {'cz': 100.0}, + 'unserverdenergycost': {'at': 6500.0, 'be': 3500.0, 'de': 1250.0, 'fr': 0.0}} + """ + + unserverd_energy_cost: t.MutableMapping[str, float] = Field( + default_factory=dict, + alias="unserverdenergycost", + description="unserverd energy cost (€/MWh) of each area", + ) + + spilled_energy_cost: t.MutableMapping[str, float] = Field( + default_factory=dict, + alias="spilledenergycost", + description="spilled energy cost (€/MWh) of each area", + ) + + @validator("unserverd_energy_cost", "spilled_energy_cost", pre=True) + def _validate_energy_cost(cls, v: t.Any) -> t.MutableMapping[str, float]: + if isinstance(v, dict): + return {str(k): float(v) for k, v in v.items()} + raise TypeError(f"Invalid type for energy cost: {type(v)}") diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/binding_constraint.py b/antarest/study/storage/rawstudy/model/filesystem/config/binding_constraint.py index a396ea950d..11749cf456 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/binding_constraint.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/binding_constraint.py @@ -1,28 +1,18 @@ -import typing as t -from enum import Enum +""" +Object model used to read and update binding constraint configuration. +""" -from pydantic import BaseModel +from antarest.study.business.enum_ignore_case import EnumIgnoreCase -class BindingConstraintFrequency(str, Enum): +class BindingConstraintFrequency(EnumIgnoreCase): """ - Frequency of binding constraint - - - HOURLY: hourly time series with 8784 lines - - DAILY: daily time series with 366 lines - - WEEKLY: weekly time series with 366 lines (same as daily) - - Usage example: - - >>> bcf = BindingConstraintFrequency.HOURLY - >>> bcf == "hourly" - True - >>> bcf = BindingConstraintFrequency.DAILY - >>> "daily" == bcf - True - >>> bcf = BindingConstraintFrequency.WEEKLY - >>> bcf != "daily" - True + Frequency of a binding constraint. + + Attributes: + HOURLY: hourly time series with 8784 lines + DAILY: daily time series with 366 lines + WEEKLY: weekly time series with 366 lines (same as daily) """ HOURLY = "hourly" @@ -30,8 +20,18 @@ class BindingConstraintFrequency(str, Enum): WEEKLY = "weekly" -class BindingConstraintDTO(BaseModel): - id: str - areas: t.Set[str] - clusters: t.Set[str] - time_step: BindingConstraintFrequency +class BindingConstraintOperator(EnumIgnoreCase): + """ + Operator of a binding constraint. + + Attributes: + LESS: less than or equal to + GREATER: greater than or equal to + BOTH: both LESS and GREATER + EQUAL: equal to + """ + + LESS = "less" + GREATER = "greater" + BOTH = "both" + EQUAL = "equal" diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/cluster.py b/antarest/study/storage/rawstudy/model/filesystem/config/cluster.py index 4563a0d217..1c84019294 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/cluster.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/cluster.py @@ -3,13 +3,12 @@ In the near future, this set of classes may be used for solar, wind and hydro clusters. """ + import functools import typing as t from pydantic import BaseModel, Extra, Field -__all__ = ("ItemProperties", "ClusterProperties") - @functools.total_ordering class ItemProperties( @@ -69,10 +68,16 @@ class ClusterProperties(ItemProperties): # Activity status: # - True: the plant may generate. # - False: not yet commissioned, moth-balled, etc. - enabled: bool = Field(default=True, description="Activity status") + enabled: bool = Field(default=True, description="Activity status", title="Enabled") # noinspection SpellCheckingInspection - unit_count: int = Field(default=1, ge=1, description="Unit count", alias="unitcount") + unit_count: int = Field( + default=1, + ge=1, + description="Unit count", + alias="unitcount", + title="Unit Count", + ) # noinspection SpellCheckingInspection nominal_capacity: float = Field( @@ -80,6 +85,7 @@ class ClusterProperties(ItemProperties): ge=0, description="Nominal capacity (MW per unit)", alias="nominalcapacity", + title="Nominal Capacity", ) @property diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/files.py b/antarest/study/storage/rawstudy/model/filesystem/config/files.py index cafc901644..6f49c9f6fa 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/files.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/files.py @@ -10,10 +10,7 @@ from antarest.core.model import JSON from antarest.study.storage.rawstudy.ini_reader import IniReader -from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import ( - BindingConstraintDTO, - BindingConstraintFrequency, -) +from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import BindingConstraintFrequency from antarest.study.storage.rawstudy.model.filesystem.config.exceptions import ( SimulationParsingError, XpansionParsingError, @@ -21,6 +18,7 @@ from antarest.study.storage.rawstudy.model.filesystem.config.field_validators import extract_filtering from antarest.study.storage.rawstudy.model.filesystem.config.model import ( Area, + BindingConstraintDTO, DistrictSet, FileStudyTreeConfig, Link, diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/ini_properties.py b/antarest/study/storage/rawstudy/model/filesystem/config/ini_properties.py new file mode 100644 index 0000000000..51f10a5ca5 --- /dev/null +++ b/antarest/study/storage/rawstudy/model/filesystem/config/ini_properties.py @@ -0,0 +1,52 @@ +import json +import typing as t + +from pydantic import BaseModel, Extra + + +class IniProperties( + BaseModel, + # On reading, if the configuration contains an extra field, it is better + # to forbid it, because it allows errors to be detected early. + # Ignoring extra attributes can hide errors. + extra=Extra.forbid, + # If a field is updated on assignment, it is also validated. + validate_assignment=True, + # On testing, we can use snake_case for field names. + allow_population_by_field_name=True, +): + """ + Base class for configuration sections. + """ + + def to_config(self) -> t.Mapping[str, t.Any]: + """ + Convert the object to a dictionary for writing to a configuration file (`*.ini`). + + Returns: + A dictionary with the configuration values. + """ + + config = {} + for field_name, field in self.__fields__.items(): + value = getattr(self, field_name) + if value is None: + continue + if isinstance(value, IniProperties): + config[field.alias] = value.to_config() + else: + config[field.alias] = json.loads(json.dumps(value)) + return config + + @classmethod + def construct(cls, _fields_set: t.Optional[t.Set[str]] = None, **values: t.Any) -> "IniProperties": + """ + Construct a new model instance from a dict of values, replacing aliases with real field names. + """ + # The pydantic construct() function does not allow aliases to be handled. + aliases = {(field.alias or name): name for name, field in cls.__fields__.items()} + renamed_values = {aliases.get(k, k): v for k, v in values.items()} + if _fields_set is not None: + _fields_set = {aliases.get(f, f) for f in _fields_set} + # noinspection PyTypeChecker + return super().construct(_fields_set, **renamed_values) diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/links.py b/antarest/study/storage/rawstudy/model/filesystem/config/links.py new file mode 100644 index 0000000000..7ebc0e2176 --- /dev/null +++ b/antarest/study/storage/rawstudy/model/filesystem/config/links.py @@ -0,0 +1,161 @@ +""" +Object model used to read and update link configuration. +""" + +import typing as t + +from pydantic import Field, root_validator, validator + +from antarest.study.business.enum_ignore_case import EnumIgnoreCase +from antarest.study.storage.rawstudy.model.filesystem.config.field_validators import ( + validate_color_rgb, + validate_colors, + validate_filtering, +) +from antarest.study.storage.rawstudy.model.filesystem.config.ini_properties import IniProperties + + +# noinspection SpellCheckingInspection +class AssetType(EnumIgnoreCase): + """ + Enum representing the type of asset for a link between two areas. + + Attributes: + AC: Represents an Alternating Current link. This is the most common type of electricity transmission. + DC: Represents a Direct Current link. This is typically used for long-distance transmission. + GAZ: Represents a gas link. This is used when the link is related to gas transmission. + VIRT: Represents a virtual link. This is used when the link doesn't physically exist + but is used for modeling purposes. + OTHER: Represents any other type of link that doesn't fall into the above categories. + """ + + AC = "ac" + DC = "dc" + GAZ = "gaz" + VIRT = "virt" + OTHER = "other" + + +class TransmissionCapacity(EnumIgnoreCase): + """ + Enum representing the transmission capacity of a link. + + Attributes: + INFINITE: Represents a link with infinite transmission capacity. + This means there are no limits on the amount of electricity that can be transmitted. + IGNORE: Represents a link where the transmission capacity is ignored. + This means the capacity is not considered during simulations. + ENABLED: Represents a link with a specific transmission capacity. + This means the capacity is considered in the model and has a certain limit. + """ + + INFINITE = "infinite" + IGNORE = "ignore" + ENABLED = "enabled" + + +class LinkProperties(IniProperties): + """ + Configuration read from a section in the `input/links//properties.ini` file. + + Usage: + + >>> from antarest.study.storage.rawstudy.model.filesystem.config.links import LinkProperties + >>> from pprint import pprint + + Create and validate a new `LinkProperties` object from a dictionary read from a configuration file. + + >>> obj = { + ... "hurdles-cost": "false", + ... "loop-flow": "false", + ... "use-phase-shifter": "false", + ... "transmission-capacities": "infinite", + ... "asset-type": "ac", + ... "link-style": "plain", + ... "link-width": "1", + ... "colorr": "80", + ... "colorg": "192", + ... "colorb": "255", + ... "comments": "This is a link", + ... "display-comments": "true", + ... "filter-synthesis": "hourly, daily, weekly, monthly, annual", + ... "filter-year-by-year": "hourly, daily, weekly, monthly, annual", + ... } + + >>> opt = LinkProperties(**obj) + + >>> pprint(opt.dict(by_alias=True), width=80) + {'asset-type': , + 'colorRgb': '#50C0FF', + 'comments': 'This is a link', + 'display-comments': True, + 'filter-synthesis': 'hourly, daily, weekly, monthly, annual', + 'filter-year-by-year': 'hourly, daily, weekly, monthly, annual', + 'hurdles-cost': False, + 'link-style': 'plain', + 'link-width': 1, + 'loop-flow': False, + 'transmission-capacities': , + 'use-phase-shifter': False} + + >>> pprint(opt.to_config(), width=80) + {'asset-type': 'ac', + 'colorb': 255, + 'colorg': 192, + 'colorr': 80, + 'comments': 'This is a link', + 'display-comments': True, + 'filter-synthesis': 'hourly, daily, weekly, monthly, annual', + 'filter-year-by-year': 'hourly, daily, weekly, monthly, annual', + 'hurdles-cost': False, + 'link-style': 'plain', + 'link-width': 1, + 'loop-flow': False, + 'transmission-capacities': 'infinite', + 'use-phase-shifter': False} + """ + + hurdles_cost: bool = Field(default=False, alias="hurdles-cost") + loop_flow: bool = Field(default=False, alias="loop-flow") + use_phase_shifter: bool = Field(default=False, alias="use-phase-shifter") + transmission_capacities: TransmissionCapacity = Field( + default=TransmissionCapacity.ENABLED, alias="transmission-capacities" + ) + asset_type: AssetType = Field(default=AssetType.AC, alias="asset-type") + link_style: str = Field(default="plain", alias="link-style") + link_width: int = Field(default=1, alias="link-width") + comments: str = Field(default="", alias="comments") # unknown field?! + display_comments: bool = Field(default=True, alias="display-comments") + filter_synthesis: str = Field(default="", alias="filter-synthesis") + filter_year_by_year: str = Field(default="", alias="filter-year-by-year") + color_rgb: str = Field( + "#707070", + alias="colorRgb", + description="color of the area in the map", + ) + + @validator("filter_synthesis", "filter_year_by_year", pre=True) + def _validate_filtering(cls, v: t.Any) -> str: + return validate_filtering(v) + + @validator("color_rgb", pre=True) + def _validate_color_rgb(cls, v: t.Any) -> str: + return validate_color_rgb(v) + + @root_validator(pre=True) + def _validate_colors(cls, values: t.MutableMapping[str, t.Any]) -> t.Mapping[str, t.Any]: + return validate_colors(values) + + # noinspection SpellCheckingInspection + def to_config(self) -> t.Mapping[str, t.Any]: + """ + Convert the object to a dictionary for writing to a configuration file. + """ + obj = dict(super().to_config()) + color_rgb = obj.pop("colorRgb", "#707070") + return { + "colorr": int(color_rgb[1:3], 16), + "colorg": int(color_rgb[3:5], 16), + "colorb": int(color_rgb[5:7], 16), + **obj, + } diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/model.py b/antarest/study/storage/rawstudy/model/filesystem/config/model.py index 18e9702571..ff79c51073 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/model.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/model.py @@ -1,21 +1,20 @@ import re import typing as t -from enum import Enum from pathlib import Path -from pydantic import Field, root_validator -from pydantic.main import BaseModel +from pydantic import BaseModel, Field, root_validator from antarest.core.utils.utils import DTO +from antarest.study.business.enum_ignore_case import EnumIgnoreCase -from .binding_constraint import BindingConstraintDTO +from .binding_constraint import BindingConstraintFrequency from .field_validators import extract_filtering from .renewable import RenewableConfigType from .st_storage import STStorageConfigType from .thermal import ThermalConfigType -class ENR_MODELLING(Enum): +class EnrModelling(EnumIgnoreCase): AGGREGATED = "aggregated" CLUSTERS = "clusters" @@ -101,6 +100,13 @@ def get_file(self) -> str: return f"{self.date}{modes[self.mode]}{dash}{self.name}" +class BindingConstraintDTO(BaseModel): + id: str + areas: t.Set[str] + clusters: t.Set[str] + time_step: BindingConstraintFrequency + + class FileStudyTreeConfig(DTO): """ Root object to handle all study parameters which impact tree structure @@ -119,7 +125,7 @@ def __init__( bindings: t.Optional[t.List[BindingConstraintDTO]] = None, store_new_set: bool = False, archive_input_series: t.Optional[t.List[str]] = None, - enr_modelling: str = ENR_MODELLING.AGGREGATED.value, + enr_modelling: str = EnrModelling.AGGREGATED.value, cache: t.Optional[t.Dict[str, t.List[str]]] = None, zip_path: t.Optional[Path] = None, ): @@ -254,7 +260,7 @@ class FileStudyTreeConfigDTO(BaseModel): bindings: t.List[BindingConstraintDTO] = list() store_new_set: bool = False archive_input_series: t.List[str] = list() - enr_modelling: str = ENR_MODELLING.AGGREGATED.value + enr_modelling: str = EnrModelling.AGGREGATED.value zip_path: t.Optional[Path] = None @staticmethod diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/renewable.py b/antarest/study/storage/rawstudy/model/filesystem/config/renewable.py index 4d34e21637..ed0716147a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/renewable.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/renewable.py @@ -6,15 +6,6 @@ from antarest.study.storage.rawstudy.model.filesystem.config.cluster import ClusterProperties from antarest.study.storage.rawstudy.model.filesystem.config.identifier import IgnoreCaseIdentifier -__all__ = ( - "TimeSeriesInterpretation", - "RenewableProperties", - "RenewableConfig", - "RenewableConfigType", - "create_renewable_config", - "RenewableClusterGroup", -) - class TimeSeriesInterpretation(EnumIgnoreCase): """ @@ -73,11 +64,13 @@ class RenewableProperties(ClusterProperties): """ group: RenewableClusterGroup = Field( + title="Renewable Cluster Group", default=RenewableClusterGroup.OTHER1, description="Renewable Cluster Group", ) ts_interpretation: TimeSeriesInterpretation = Field( + title="Time Series Interpretation", default=TimeSeriesInterpretation.POWER_GENERATION, description="Time series interpretation", alias="ts-interpretation", @@ -105,6 +98,22 @@ class RenewableConfig(RenewableProperties, IgnoreCaseIdentifier): RenewableConfigType = RenewableConfig +def get_renewable_config_cls(study_version: t.Union[str, int]) -> t.Type[RenewableConfig]: + """ + Retrieves the renewable configuration class based on the study version. + + Args: + study_version: The version of the study. + + Returns: + The renewable configuration class. + """ + version = int(study_version) + if version >= 810: + return RenewableConfig + raise ValueError(f"Unsupported study version {study_version}, required 810 or above.") + + def create_renewable_config(study_version: t.Union[str, int], **kwargs: t.Any) -> RenewableConfigType: """ Factory method to create a renewable configuration model. @@ -119,4 +128,5 @@ def create_renewable_config(study_version: t.Union[str, int], **kwargs: t.Any) - Raises: ValueError: If the study version is not supported. """ - return RenewableConfig(**kwargs) + cls = get_renewable_config_cls(study_version) + return cls(**kwargs) diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/st_storage.py b/antarest/study/storage/rawstudy/model/filesystem/config/st_storage.py index 58efc0ceb8..3355ba571a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/st_storage.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/st_storage.py @@ -6,14 +6,6 @@ from antarest.study.storage.rawstudy.model.filesystem.config.cluster import ItemProperties from antarest.study.storage.rawstudy.model.filesystem.config.identifier import LowerCaseIdentifier -__all__ = ( - "STStorageGroup", - "STStorageProperties", - "STStorageConfig", - "STStorageConfigType", - "create_st_storage_config", -) - class STStorageGroup(EnumIgnoreCase): """ @@ -50,46 +42,64 @@ class STStorageProperties(ItemProperties): group: STStorageGroup = Field( STStorageGroup.OTHER1, description="Energy storage system group", + title="Short-Term Storage Group", ) injection_nominal_capacity: float = Field( 0, description="Injection nominal capacity (MW)", ge=0, alias="injectionnominalcapacity", + title="Injection Nominal Capacity", ) withdrawal_nominal_capacity: float = Field( 0, description="Withdrawal nominal capacity (MW)", ge=0, alias="withdrawalnominalcapacity", + title="Withdrawal Nominal Capacity", ) reservoir_capacity: float = Field( 0, description="Reservoir capacity (MWh)", ge=0, alias="reservoircapacity", + title="Reservoir Capacity", ) efficiency: float = Field( 1, description="Efficiency of the storage system (%)", ge=0, le=1, + title="Efficiency", ) - # The `initial_level` value must be between 0 and 1, but the default value is 0. + # The `initial_level` value must be between 0 and 1, but the default value is 0.5 initial_level: float = Field( 0.5, description="Initial level of the storage system (%)", ge=0, le=1, alias="initiallevel", + title="Initial Level", ) initial_level_optim: bool = Field( False, description="Flag indicating if the initial level is optimized", alias="initialleveloptim", + title="Initial Level Optimization", ) +class STStorage880Properties(STStorageProperties): + """ + Short term storage configuration model for 880 study. + """ + + # Activity status: + # - True: the plant may generate. + # - False: Ignored by the simulator. + enabled: bool = Field(default=True, description="Activity status") + + # noinspection SpellCheckingInspection class STStorageConfig(STStorageProperties, LowerCaseIdentifier): """ @@ -116,7 +126,45 @@ class STStorageConfig(STStorageProperties, LowerCaseIdentifier): """ -STStorageConfigType = STStorageConfig +class STStorage880Config(STStorage880Properties, LowerCaseIdentifier): + """ + Short Term Storage properties for study in version 8.8 or above. + + Usage: + + >>> from antarest.study.storage.rawstudy.model.filesystem.config.st_storage import STStorage880Config + + >>> st = STStorage880Config(name="Storage 1", group="battery", enabled=False) + >>> st.id + 'storage 1' + >>> st.group == STStorageGroup.BATTERY + True + >>> st.enabled + False + """ + + +# NOTE: In the following Union, it is important to place the older version first, +# because otherwise, creating a short term storage always creates a v8.8 one. +STStorageConfigType = t.Union[STStorageConfig, STStorage880Config] + + +def get_st_storage_config_cls(study_version: t.Union[str, int]) -> t.Type[STStorageConfigType]: + """ + Retrieves the short-term storage configuration class based on the study version. + + Args: + study_version: The version of the study. + + Returns: + The short-term storage configuration class. + """ + version = int(study_version) + if version >= 880: + return STStorage880Config + elif version >= 860: + return STStorageConfig + raise ValueError(f"Unsupported study version: {version}") def create_st_storage_config(study_version: t.Union[str, int], **kwargs: t.Any) -> STStorageConfigType: @@ -133,7 +181,5 @@ def create_st_storage_config(study_version: t.Union[str, int], **kwargs: t.Any) Raises: ValueError: If the study version is not supported. """ - version = int(study_version) - if version < 860: - raise ValueError(f"Unsupported study version: {version}") - return STStorageConfig(**kwargs) + cls = get_st_storage_config_cls(study_version) + return cls(**kwargs) diff --git a/antarest/study/storage/rawstudy/model/filesystem/config/thermal.py b/antarest/study/storage/rawstudy/model/filesystem/config/thermal.py index e9a663e9ac..dcd0bc7729 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/config/thermal.py +++ b/antarest/study/storage/rawstudy/model/filesystem/config/thermal.py @@ -6,18 +6,6 @@ from antarest.study.storage.rawstudy.model.filesystem.config.cluster import ClusterProperties from antarest.study.storage.rawstudy.model.filesystem.config.identifier import IgnoreCaseIdentifier -__all__ = ( - "LocalTSGenerationBehavior", - "LawOption", - "ThermalClusterGroup", - "ThermalProperties", - "Thermal860Properties", - "ThermalConfig", - "Thermal860Config", - "ThermalConfigType", - "create_thermal_config", -) - class LocalTSGenerationBehavior(EnumIgnoreCase): """ @@ -34,7 +22,7 @@ class LocalTSGenerationBehavior(EnumIgnoreCase): FORCE_NO_GENERATION = "force no generation" FORCE_GENERATION = "force generation" - def __repr__(self) -> str: + def __repr__(self) -> str: # pragma: no cover return f"{self.__class__.__name__}.{self.name}" @@ -47,7 +35,7 @@ class LawOption(EnumIgnoreCase): UNIFORM = "uniform" GEOMETRIC = "geometric" - def __repr__(self) -> str: + def __repr__(self) -> str: # pragma: no cover return f"{self.__class__.__name__}.{self.name}" @@ -68,7 +56,7 @@ class ThermalClusterGroup(EnumIgnoreCase): OTHER3 = "Other 3" OTHER4 = "Other 4" - def __repr__(self) -> str: + def __repr__(self) -> str: # pragma: no cover return f"{self.__class__.__name__}.{self.name}" @classmethod @@ -87,6 +75,16 @@ def _missing_(cls, value: object) -> t.Optional["ThermalClusterGroup"]: return t.cast(t.Optional["ThermalClusterGroup"], super()._missing_(value)) +class ThermalCostGeneration(EnumIgnoreCase): + """ + Specifies how to generate thermal cluster cost. + The value `SetManually` is used by default. + """ + + SET_MANUALLY = "SetManually" + USE_COST_TIME_SERIES = "useCostTimeseries" + + class ThermalProperties(ClusterProperties): """ Thermal cluster configuration model. @@ -96,17 +94,20 @@ class ThermalProperties(ClusterProperties): group: ThermalClusterGroup = Field( default=ThermalClusterGroup.OTHER1, description="Thermal Cluster Group", + title="Thermal Cluster Group", ) gen_ts: LocalTSGenerationBehavior = Field( default=LocalTSGenerationBehavior.USE_GLOBAL, description="Time Series Generation Option", alias="gen-ts", + title="Time Series Generation", ) min_stable_power: float = Field( default=0.0, description="Min. Stable Power (MW)", alias="min-stable-power", + title="Min. Stable Power", ) min_up_time: int = Field( default=1, @@ -114,6 +115,7 @@ class ThermalProperties(ClusterProperties): le=168, description="Min. Up time (h)", alias="min-up-time", + title="Min. Up Time", ) min_down_time: int = Field( default=1, @@ -121,17 +123,20 @@ class ThermalProperties(ClusterProperties): le=168, description="Min. Down time (h)", alias="min-down-time", + title="Min. Down Time", ) must_run: bool = Field( default=False, description="Must run flag", alias="must-run", + title="Must Run", ) spinning: float = Field( default=0.0, ge=0, le=100, description="Spinning (%)", + title="Spinning", ) volatility_forced: float = Field( default=0.0, @@ -139,6 +144,7 @@ class ThermalProperties(ClusterProperties): le=1, description="Forced Volatility", alias="volatility.forced", + title="Forced Volatility", ) volatility_planned: float = Field( default=0.0, @@ -146,51 +152,60 @@ class ThermalProperties(ClusterProperties): le=1, description="Planned volatility", alias="volatility.planned", + title="Planned Volatility", ) law_forced: LawOption = Field( default=LawOption.UNIFORM, description="Forced Law (ts-generator)", alias="law.forced", + title="Forced Law", ) law_planned: LawOption = Field( default=LawOption.UNIFORM, description="Planned Law (ts-generator)", alias="law.planned", + title="Planned Law", ) marginal_cost: float = Field( default=0.0, ge=0, description="Marginal cost (euros/MWh)", alias="marginal-cost", + title="Marginal Cost", ) spread_cost: float = Field( default=0.0, ge=0, description="Spread (euros/MWh)", alias="spread-cost", + title="Spread Cost", ) fixed_cost: float = Field( default=0.0, ge=0, description="Fixed cost (euros/hour)", alias="fixed-cost", + title="Fixed Cost", ) startup_cost: float = Field( default=0.0, ge=0, description="Startup cost (euros/startup)", alias="startup-cost", + title="Startup Cost", ) market_bid_cost: float = Field( default=0.0, ge=0, description="Market bid cost (euros/MWh)", alias="market-bid-cost", + title="Market Bid Cost", ) co2: float = Field( default=0.0, ge=0, description="Emission rate of CO2 (t/MWh)", + title="Emission rate of CO2", ) @@ -203,62 +218,102 @@ class Thermal860Properties(ThermalProperties): default=0.0, ge=0, description="Emission rate of NH3 (t/MWh)", + title="Emission rate of NH3", ) so2: float = Field( default=0.0, ge=0, description="Emission rate of SO2 (t/MWh)", + title="Emission rate of SO2", ) nox: float = Field( default=0.0, ge=0, description="Emission rate of NOX (t/MWh)", + title="Emission rate of NOX", ) pm2_5: float = Field( default=0.0, ge=0, description="Emission rate of PM 2.5 (t/MWh)", + title="Emission rate of PM 2.5", alias="pm2_5", ) pm5: float = Field( default=0.0, ge=0, description="Emission rate of PM 5 (t/MWh)", + title="Emission rate of PM 5", ) pm10: float = Field( default=0.0, ge=0, description="Emission rate of PM 10 (t/MWh)", + title="Emission rate of PM 10", ) nmvoc: float = Field( default=0.0, ge=0, description="Emission rate of NMVOC (t/MWh)", + title="Emission rate of NMVOC", ) op1: float = Field( default=0.0, ge=0, description="Emission rate of pollutant 1 (t/MWh)", + title="Emission rate of pollutant 1", ) op2: float = Field( default=0.0, ge=0, description="Emission rate of pollutant 2 (t/MWh)", + title="Emission rate of pollutant 2", ) op3: float = Field( default=0.0, ge=0, description="Emission rate of pollutant 3 (t/MWh)", + title="Emission rate of pollutant 3", ) op4: float = Field( default=0.0, ge=0, description="Emission rate of pollutant 4 (t/MWh)", + title="Emission rate of pollutant 4", ) op5: float = Field( default=0.0, ge=0, description="Emission rate of pollutant 5 (t/MWh)", + title="Emission rate of pollutant 5", + ) + + +# noinspection SpellCheckingInspection +class Thermal870Properties(Thermal860Properties): + """ + Thermal cluster configuration model for study in version 8.7 or above. + """ + + cost_generation: ThermalCostGeneration = Field( + default=ThermalCostGeneration.SET_MANUALLY, + alias="costgeneration", + description="Cost generation option", + title="Cost Generation", + ) + efficiency: float = Field( + default=100.0, + ge=0, + le=100, + description="Efficiency (%)", + title="Efficiency", + ) + # Even if `variableomcost` is a cost it could be negative. + variable_o_m_cost: float = Field( + default=0.0, + description="Operating and Maintenance Cost (€/MWh)", + alias="variableomcost", + title="Variable O&M Cost", ) @@ -285,7 +340,7 @@ class ThermalConfig(ThermalProperties, IgnoreCaseIdentifier): class Thermal860Config(Thermal860Properties, IgnoreCaseIdentifier): """ - Thermal properties for study in version 8.6 or above. + Thermal properties for study in version 860 Usage: @@ -305,9 +360,56 @@ class Thermal860Config(Thermal860Properties, IgnoreCaseIdentifier): """ +class Thermal870Config(Thermal870Properties, IgnoreCaseIdentifier): + """ + Thermal properties for study in version 8.7 or above. + + Usage: + + >>> from antarest.study.storage.rawstudy.model.filesystem.config.thermal import Thermal870Config + + >>> cl = Thermal870Config(name="cluster 01!", group="Nuclear", co2=123, nh3=456, efficiency=97) + >>> cl.id + 'cluster 01' + >>> cl.group == ThermalClusterGroup.NUCLEAR + True + >>> cl.co2 + 123.0 + >>> cl.nh3 + 456.0 + >>> cl.op1 + 0.0 + >>> cl.efficiency + 97.0 + >>> cl.variable_o_m_cost + 0.0 + >>> cl.cost_generation == ThermalCostGeneration.SET_MANUALLY + True + """ + + # NOTE: In the following Union, it is important to place the most specific type first, # because the type matching generally occurs sequentially from left to right within the union. -ThermalConfigType = t.Union[Thermal860Config, ThermalConfig] +ThermalConfigType = t.Union[Thermal870Config, Thermal860Config, ThermalConfig] + + +def get_thermal_config_cls(study_version: t.Union[str, int]) -> t.Type[ThermalConfigType]: + """ + Retrieves the thermal configuration class based on the study version. + + Args: + study_version: The version of the study. + + Returns: + The thermal configuration class. + """ + version = int(study_version) + if version >= 870: + return Thermal870Config + elif version == 860: + return Thermal860Config + else: + return ThermalConfig def create_thermal_config(study_version: t.Union[str, int], **kwargs: t.Any) -> ThermalConfigType: @@ -324,8 +426,5 @@ def create_thermal_config(study_version: t.Union[str, int], **kwargs: t.Any) -> Raises: ValueError: If the study version is not supported. """ - version = int(study_version) - if version >= 860: - return Thermal860Config(**kwargs) - else: - return ThermalConfig(**kwargs) + cls = get_thermal_config_cls(study_version) + return cls(**kwargs) diff --git a/antarest/study/storage/rawstudy/model/filesystem/folder_node.py b/antarest/study/storage/rawstudy/model/filesystem/folder_node.py index 7d174cfbc6..3ea51c098d 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/folder_node.py +++ b/antarest/study/storage/rawstudy/model/filesystem/folder_node.py @@ -1,7 +1,7 @@ import shutil +import typing as t from abc import ABC, abstractmethod from http import HTTPStatus -from typing import Dict, List, Optional, Tuple, Union from fastapi import HTTPException @@ -38,7 +38,7 @@ def __init__( self, context: ContextServer, config: FileStudyTreeConfig, - children_glob_exceptions: Optional[List[str]] = None, + children_glob_exceptions: t.Optional[t.List[str]] = None, ) -> None: super().__init__(config) self.context = context @@ -50,11 +50,11 @@ def build(self) -> TREE: def _forward_get( self, - url: List[str], + url: t.List[str], depth: int = -1, formatted: bool = True, get_node: bool = False, - ) -> Union[JSON, INode[JSON, SUB_JSON, JSON]]: + ) -> t.Union[JSON, INode[JSON, SUB_JSON, JSON]]: children = self.build() names, sub_url = self.extract_child(children, url) @@ -84,7 +84,7 @@ def _forward_get( def _expand_get( self, depth: int = -1, formatted: bool = True, get_node: bool = False - ) -> Union[JSON, INode[JSON, SUB_JSON, JSON]]: + ) -> t.Union[JSON, INode[JSON, SUB_JSON, JSON]]: if get_node: return self @@ -99,11 +99,11 @@ def _expand_get( def _get( self, - url: Optional[List[str]] = None, + url: t.Optional[t.List[str]] = None, depth: int = -1, formatted: bool = True, get_node: bool = False, - ) -> Union[JSON, INode[JSON, SUB_JSON, JSON]]: + ) -> t.Union[JSON, INode[JSON, SUB_JSON, JSON]]: if url and url != [""]: return self._forward_get(url, depth, formatted, get_node) else: @@ -111,7 +111,7 @@ def _get( def get( self, - url: Optional[List[str]] = None, + url: t.Optional[t.List[str]] = None, depth: int = -1, expanded: bool = False, formatted: bool = True, @@ -122,7 +122,7 @@ def get( def get_node( self, - url: Optional[List[str]] = None, + url: t.Optional[t.List[str]] = None, ) -> INode[JSON, SUB_JSON, JSON]: output = self._get(url=url, get_node=True) assert isinstance(output, INode) @@ -131,7 +131,7 @@ def get_node( def save( self, data: SUB_JSON, - url: Optional[List[str]] = None, + url: t.Optional[t.List[str]] = None, ) -> None: self._assert_not_in_zipped_file() children = self.build() @@ -146,7 +146,7 @@ def save( for key in data: children[key].save(data[key]) - def delete(self, url: Optional[List[str]] = None) -> None: + def delete(self, url: t.Optional[t.List[str]] = None) -> None: if url and url != [""]: children = self.build() names, sub_url = self.extract_child(children, url) @@ -158,16 +158,16 @@ def delete(self, url: Optional[List[str]] = None) -> None: def check_errors( self, data: JSON, - url: Optional[List[str]] = None, + url: t.Optional[t.List[str]] = None, raising: bool = False, - ) -> List[str]: + ) -> t.List[str]: children = self.build() if url and url != [""]: (name,), sub_url = self.extract_child(children, url) return children[name].check_errors(data, sub_url, raising) else: - errors: List[str] = [] + errors: t.List[str] = [] for key in data: if key not in children: msg = f"key={key} not in {list(children.keys())} for {self.__class__.__name__}" @@ -186,7 +186,7 @@ def denormalize(self) -> None: for child in self.build().values(): child.denormalize() - def extract_child(self, children: TREE, url: List[str]) -> Tuple[List[str], List[str]]: + def extract_child(self, children: TREE, url: t.List[str]) -> t.Tuple[t.List[str], t.List[str]]: names, sub_url = url[0].split(","), url[1:] names = ( list( @@ -208,6 +208,6 @@ def extract_child(self, children: TREE, url: List[str]) -> Tuple[List[str], List for name in names: if name not in children: raise ChildNotFoundError(f"'{name}' not a child of {self.__class__.__name__}") - if type(children[name]) != child_class: + if not isinstance(children[name], child_class): raise FilterError("Filter selection has different classes") return names, sub_url diff --git a/antarest/study/storage/rawstudy/model/filesystem/json_file_node.py b/antarest/study/storage/rawstudy/model/filesystem/json_file_node.py index ee14da91ea..80f607485d 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/json_file_node.py +++ b/antarest/study/storage/rawstudy/model/filesystem/json_file_node.py @@ -1,6 +1,6 @@ import json +import typing as t from pathlib import Path -from typing import Any, Dict, Optional, cast from antarest.core.model import JSON from antarest.study.storage.rawstudy.ini_reader import IReader @@ -11,13 +11,41 @@ class JsonReader(IReader): - def read(self, path: Any) -> JSON: - if isinstance(path, Path): - return cast(JSON, json.loads(path.read_text(encoding="utf-8"))) - return cast(JSON, json.loads(path)) + """ + JSON file reader. + """ + + def read(self, path: t.Any) -> JSON: + content: t.Union[str, bytes] + + if isinstance(path, (Path, str)): + try: + with open(path, mode="r", encoding="utf-8") as f: + content = f.read() + except FileNotFoundError: + # If the file is missing, an empty dictionary is returned, + # to mimic the behavior of `configparser.ConfigParser`. + return {} + + elif hasattr(path, "read"): + with path: + content = path.read() + + else: # pragma: no cover + raise TypeError(repr(type(path))) + + try: + return t.cast(JSON, json.loads(content)) + except json.JSONDecodeError as exc: + err_msg = f"Failed to parse JSON file '{path}'" + raise ValueError(err_msg) from exc class JsonWriter(IniWriter): + """ + JSON file writer. + """ + def write(self, data: JSON, path: Path) -> None: with open(path, "w") as fh: json.dump(data, fh) @@ -28,6 +56,6 @@ def __init__( self, context: ContextServer, config: FileStudyTreeConfig, - types: Optional[Dict[str, Any]] = None, + types: t.Optional[t.Dict[str, t.Any]] = None, ) -> None: super().__init__(context, config, types, JsonReader(), JsonWriter()) diff --git a/antarest/study/storage/rawstudy/model/filesystem/matrix/date_serializer.py b/antarest/study/storage/rawstudy/model/filesystem/matrix/date_serializer.py index 37e0badb0c..909140b68a 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/matrix/date_serializer.py +++ b/antarest/study/storage/rawstudy/model/filesystem/matrix/date_serializer.py @@ -68,7 +68,7 @@ class HourlyMatrixSerializer(IDateMatrixSerializer): def build_date(self, index: pd.Index) -> pd.DataFrame: def _map(row: str) -> Tuple[str, int, str, str, str]: - m, d, h = re.split("[\s/]", row) + m, d, h = re.split(r"[\s/]", row) return "", 1, d, IDateMatrixSerializer._R_MONTHS[m], h items = index.map(_map).tolist() diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/bindingconstraints/bindingcontraints.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/bindingconstraints/bindingcontraints.py index 69fe669183..8ef625200c 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/bindingconstraints/bindingcontraints.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/bindingconstraints/bindingcontraints.py @@ -6,9 +6,17 @@ from antarest.study.storage.rawstudy.model.filesystem.root.input.bindingconstraints.bindingconstraints_ini import ( BindingConstraintsIni, ) -from antarest.study.storage.variantstudy.business.matrix_constants.binding_constraint.series import ( - default_bc_hourly, - default_bc_weekly_daily, +from antarest.study.storage.variantstudy.business.matrix_constants.binding_constraint.series_after_v87 import ( + default_bc_hourly as default_bc_hourly_87, +) +from antarest.study.storage.variantstudy.business.matrix_constants.binding_constraint.series_after_v87 import ( + default_bc_weekly_daily as default_bc_weekly_daily_87, +) +from antarest.study.storage.variantstudy.business.matrix_constants.binding_constraint.series_before_v87 import ( + default_bc_hourly as default_bc_hourly_86, +) +from antarest.study.storage.variantstudy.business.matrix_constants.binding_constraint.series_before_v87 import ( + default_bc_weekly_daily as default_bc_weekly_daily_86, ) @@ -19,23 +27,40 @@ class BindingConstraints(FolderNode): """ def build(self) -> TREE: - default_matrices = { - BindingConstraintFrequency.HOURLY: default_bc_hourly, - BindingConstraintFrequency.DAILY: default_bc_weekly_daily, - BindingConstraintFrequency.WEEKLY: default_bc_weekly_daily, - } - children: TREE = { - binding.id: InputSeriesMatrix( - self.context, - self.config.next_file(f"{binding.id}.txt"), - freq=MatrixFrequency(binding.time_step), - nb_columns=3, - default_empty=default_matrices[binding.time_step], - ) - for binding in self.config.bindings - } - - # noinspection SpellCheckingInspection + cfg = self.config + if cfg.version < 870: + default_matrices = { + BindingConstraintFrequency.HOURLY: default_bc_hourly_86, + BindingConstraintFrequency.DAILY: default_bc_weekly_daily_86, + BindingConstraintFrequency.WEEKLY: default_bc_weekly_daily_86, + } + children: TREE = { + binding.id: InputSeriesMatrix( + self.context, + self.config.next_file(f"{binding.id}.txt"), + freq=MatrixFrequency(binding.time_step), + nb_columns=3, + default_empty=default_matrices[binding.time_step], + ) + for binding in self.config.bindings + } + else: + default_matrices = { + BindingConstraintFrequency.HOURLY: default_bc_hourly_87, + BindingConstraintFrequency.DAILY: default_bc_weekly_daily_87, + BindingConstraintFrequency.WEEKLY: default_bc_weekly_daily_87, + } + children = {} + for binding in self.config.bindings: + for term in ["lt", "gt", "eq"]: + matrix_id = f"{binding.id}_{term}" + children[matrix_id] = InputSeriesMatrix( + self.context, + self.config.next_file(f"{matrix_id}.txt"), + freq=MatrixFrequency(binding.time_step), + nb_columns=1 if term in ["lt", "gt"] else None, + default_empty=default_matrices[binding.time_step], + ) children["bindingconstraints"] = BindingConstraintsIni( self.context, self.config.next_file("bindingconstraints.ini") ) diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/hydro_ini.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/hydro_ini.py index 95f48a48f3..9e07a32506 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/hydro_ini.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/hydro/hydro_ini.py @@ -5,6 +5,7 @@ class InputHydroIni(IniFileNode): def __init__(self, context: ContextServer, config: FileStudyTreeConfig): + # TODO: missing "use heuristic", "follow load" and "reservoir capacity" sections = [ "inter-daily-breakdown", "intra-daily-modulation", diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/input.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/input.py index 88b58c5369..4e26ff0c9c 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/input.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/input.py @@ -1,4 +1,4 @@ -from antarest.study.storage.rawstudy.model.filesystem.config.model import ENR_MODELLING +from antarest.study.storage.rawstudy.model.filesystem.config.model import EnrModelling from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.root.input.areas.areas import InputAreas @@ -37,7 +37,7 @@ def build(self) -> TREE: "wind": InputWind(self.context, self.config.next_file("wind")), } - if self.config.enr_modelling == ENR_MODELLING.CLUSTERS.value: + if self.config.enr_modelling == EnrModelling.CLUSTERS.value: children["renewables"] = ClusteredRenewables(self.context, self.config.next_file("renewables")) if self.config.version >= 860: children["st-storage"] = InputSTStorage(self.context, self.config.next_file("st-storage")) diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/area/thermal/thermal.py b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/area/thermal/thermal.py index a93c4378cb..c11083a882 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/area/thermal/thermal.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/input/thermal/series/area/thermal/thermal.py @@ -2,6 +2,7 @@ from antarest.study.storage.rawstudy.model.filesystem.inode import TREE from antarest.study.storage.rawstudy.model.filesystem.matrix.constants import default_scenario_hourly from antarest.study.storage.rawstudy.model.filesystem.matrix.input_series_matrix import InputSeriesMatrix +from antarest.study.storage.rawstudy.model.filesystem.matrix.matrix import MatrixFrequency class InputThermalSeriesAreaThermal(FolderNode): @@ -13,4 +14,17 @@ def build(self) -> TREE: default_empty=default_scenario_hourly, ), } + if self.config.version >= 870: + children["CO2Cost"] = InputSeriesMatrix( + self.context, + self.config.next_file("CO2Cost.txt"), + freq=MatrixFrequency.HOURLY, + default_empty=default_scenario_hourly, + ) + children["fuelCost"] = InputSeriesMatrix( + self.context, + self.config.next_file("fuelCost.txt"), + freq=MatrixFrequency.HOURLY, + default_empty=default_scenario_hourly, + ) return children diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/area.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/area.py index d2b9541a22..dc5726554d 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/area.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/mode/common/area.py @@ -53,7 +53,7 @@ def build(self) -> TREE: self.area, ) - # has_enr_clusters = self.config.enr_modelling == ENR_MODELLING.CLUSTERS.value and + # has_enr_clusters = self.config.enr_modelling == EnrModelling.CLUSTERS.value and # len(self.config.get_renewable_ids(self.area)) > 0 # todo get the config related to this output (now this may fail if input has changed since the launch) has_enr_clusters = True diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_numbers/ts_numbers.py b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_numbers/ts_numbers.py index 5c977c1dd4..2a74e256f9 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_numbers/ts_numbers.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/output/simulation/ts_numbers/ts_numbers.py @@ -1,6 +1,7 @@ from antarest.study.storage.rawstudy.model.filesystem.common.area_matrix_list import ( AreaMatrixList, AreaMultipleMatrixList, + BindingConstraintMatrixList, ThermalMatrixList, ) from antarest.study.storage.rawstudy.model.filesystem.folder_node import FolderNode @@ -10,17 +11,24 @@ ) +# noinspection SpellCheckingInspection class OutputSimulationTsNumbers(FolderNode): """ Represents a folder structure, which contains several time series folders (one for each generator type: "hydro", "load", "solar" and "wind") and a specific folder structure for the thermal clusters (one for each area). + Since v8.7, it also contains a folder for the binding constraints. + Example of tree structure: .. code-block:: text output/20230323-1540adq/ts-numbers/ + ├── bindingconstraints + │ ├── group_1.txt + │ ├── group_2.txt + │ └── [...] ├── hydro │ ├── at.txt │ ├── ch.txt @@ -77,4 +85,10 @@ def build(self) -> TREE: TsNumbersVector, ), } + if self.config.version >= 870: + children["bindingconstraints"] = BindingConstraintMatrixList( + self.context, + self.config.next_file("bindingconstraints"), + matrix_class=TsNumbersVector, + ) return children diff --git a/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/expansion.py b/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/expansion.py index 2b7414234f..c38246f6cf 100644 --- a/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/expansion.py +++ b/antarest/study/storage/rawstudy/model/filesystem/root/user/expansion/expansion.py @@ -14,11 +14,7 @@ class Expansion(BucketNode): registered_files = [ - RegisteredFile( - key="candidates", - node=ExpansionCandidates, - filename="candidates.ini", - ), + RegisteredFile(key="candidates", node=ExpansionCandidates, filename="candidates.ini"), RegisteredFile(key="settings", node=ExpansionSettings, filename="settings.ini"), RegisteredFile(key="capa", node=ExpansionMatrixResources), RegisteredFile(key="weights", node=ExpansionMatrixResources), diff --git a/antarest/study/storage/rawstudy/watcher.py b/antarest/study/storage/rawstudy/watcher.py index d2b5c9883c..8f593ce0d6 100644 --- a/antarest/study/storage/rawstudy/watcher.py +++ b/antarest/study/storage/rawstudy/watcher.py @@ -94,6 +94,7 @@ def _loop(self) -> None: "Removing duplicates, this is a temporary fix that should be removed when previous duplicates are removed" ) with db(): + # in this part full `Read` rights over studies are granted to this function self.study_service.remove_duplicates() except Exception as e: logger.error("Unexpected error when removing duplicates", exc_info=e) diff --git a/antarest/study/storage/study_download_utils.py b/antarest/study/storage/study_download_utils.py index 9cc25d5586..c89d60b380 100644 --- a/antarest/study/storage/study_download_utils.py +++ b/antarest/study/storage/study_download_utils.py @@ -22,7 +22,7 @@ StudyDownloadType, TimeSerie, ) -from antarest.study.storage.rawstudy.model.filesystem.config.model import ENR_MODELLING, Area, FileStudyTreeConfig +from antarest.study.storage.rawstudy.model.filesystem.config.model import Area, EnrModelling, FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy from antarest.study.storage.rawstudy.model.filesystem.folder_node import ChildNotFoundError, FilterError, FolderNode from antarest.study.storage.rawstudy.model.filesystem.inode import INode @@ -98,7 +98,7 @@ def level_output_filter( data: StudyDownloadDTO, ) -> None: cluster_details = [f"details-{data.level.value}"] - if study.config.enr_modelling == ENR_MODELLING.CLUSTERS.value: + if study.config.enr_modelling == EnrModelling.CLUSTERS.value: cluster_details += [f"details-res-{data.level.value}"] files_matcher = ( diff --git a/antarest/study/storage/study_upgrader/__init__.py b/antarest/study/storage/study_upgrader/__init__.py index 1993b4a0c3..6bfbf712be 100644 --- a/antarest/study/storage/study_upgrader/__init__.py +++ b/antarest/study/storage/study_upgrader/__init__.py @@ -3,10 +3,10 @@ import shutil import tempfile import time +import typing as t from http import HTTPStatus from http.client import HTTPException from pathlib import Path -from typing import Callable, List, NamedTuple from antarest.core.exceptions import StudyValidationError @@ -19,44 +19,40 @@ from .upgrader_840 import upgrade_840 from .upgrader_850 import upgrade_850 from .upgrader_860 import upgrade_860 +from .upgrader_870 import upgrade_870 +from .upgrader_880 import upgrade_880 + +STUDY_ANTARES = "study.antares" +""" +Main file of an Antares study containing the caption, the version, the creation date, etc. +""" logger = logging.getLogger(__name__) -class UpgradeMethod(NamedTuple): +class UpgradeMethod(t.NamedTuple): """Raw study upgrade method (old version, new version, upgrade function).""" old: str new: str - method: Callable[[Path], None] - files: List[Path] + method: t.Callable[[Path], None] + files: t.List[Path] + +_GENERAL_DATA_PATH = Path("settings/generaldata.ini") UPGRADE_METHODS = [ - UpgradeMethod("700", "710", upgrade_710, [Path("settings/generaldata.ini")]), + UpgradeMethod("700", "710", upgrade_710, [_GENERAL_DATA_PATH]), UpgradeMethod("710", "720", upgrade_720, []), - UpgradeMethod("720", "800", upgrade_800, [Path("settings/generaldata.ini")]), - UpgradeMethod( - "800", - "810", - upgrade_810, - [Path("settings/generaldata.ini"), Path("input")], - ), + UpgradeMethod("720", "800", upgrade_800, [_GENERAL_DATA_PATH]), + UpgradeMethod("800", "810", upgrade_810, [_GENERAL_DATA_PATH, Path("input")]), UpgradeMethod("810", "820", upgrade_820, [Path("input/links")]), - UpgradeMethod( - "820", - "830", - upgrade_830, - [Path("settings/generaldata.ini"), Path("input/areas")], - ), - UpgradeMethod("830", "840", upgrade_840, [Path("settings/generaldata.ini")]), - UpgradeMethod("840", "850", upgrade_850, [Path("settings/generaldata.ini")]), - UpgradeMethod( - "850", - "860", - upgrade_860, - [Path("input"), Path("settings/generaldata.ini")], - ), + UpgradeMethod("820", "830", upgrade_830, [_GENERAL_DATA_PATH, Path("input/areas")]), + UpgradeMethod("830", "840", upgrade_840, [_GENERAL_DATA_PATH]), + UpgradeMethod("840", "850", upgrade_850, [_GENERAL_DATA_PATH]), + UpgradeMethod("850", "860", upgrade_860, [Path("input"), _GENERAL_DATA_PATH]), + UpgradeMethod("860", "870", upgrade_870, [Path("input/thermal"), Path("input/bindingconstraints")]), + UpgradeMethod("870", "880", upgrade_880, [Path("input/st-storage/clusters")]), ] @@ -115,7 +111,7 @@ def get_current_version(study_path: Path) -> str: `study.antares` file or does not match the expected format. """ - antares_path = study_path / "study.antares" + antares_path = study_path / STUDY_ANTARES pattern = r"version\s*=\s*([\w.-]+)\s*" with antares_path.open(encoding="utf-8") as lines: for line in lines: @@ -127,7 +123,7 @@ def get_current_version(study_path: Path) -> str: ) -def can_upgrade_version(from_version: str, to_version: str) -> List[Path]: +def can_upgrade_version(from_version: str, to_version: str) -> t.List[Path]: """ Checks if upgrading from one version to another is possible. @@ -173,8 +169,8 @@ def can_upgrade_version(from_version: str, to_version: str) -> List[Path]: def _update_study_antares_file(target_version: str, study_path: Path) -> None: - file = study_path / "study.antares" - content = file.read_text(encoding="utf-8") + antares_path = study_path / STUDY_ANTARES + content = antares_path.read_text(encoding="utf-8") content = re.sub( r"^version\s*=.*$", f"version = {target_version}", @@ -187,10 +183,10 @@ def _update_study_antares_file(target_version: str, study_path: Path) -> None: content, flags=re.MULTILINE, ) - file.write_text(content, encoding="utf-8") + antares_path.write_text(content, encoding="utf-8") -def _copies_only_necessary_files(files_to_upgrade: List[Path], study_path: Path, tmp_path: Path) -> List[Path]: +def _copies_only_necessary_files(files_to_upgrade: t.List[Path], study_path: Path, tmp_path: Path) -> t.List[Path]: """ Copies files concerned by the version upgrader into a temporary directory. Args: @@ -202,10 +198,13 @@ def _copies_only_necessary_files(files_to_upgrade: List[Path], study_path: Path, without any children that has parents already in the list. """ files_to_copy = _filters_out_children_files(files_to_upgrade) - files_to_copy.append(Path("study.antares")) + files_to_copy.append(Path(STUDY_ANTARES)) files_to_retrieve = [] for path in files_to_copy: entire_path = study_path / path + if not entire_path.exists(): + # This can happen when upgrading a study to v8.8. + continue if entire_path.is_dir(): if not (tmp_path / path).exists(): shutil.copytree(entire_path, tmp_path / path, dirs_exist_ok=True) @@ -221,7 +220,7 @@ def _copies_only_necessary_files(files_to_upgrade: List[Path], study_path: Path, return files_to_retrieve -def _filters_out_children_files(files_to_upgrade: List[Path]) -> List[Path]: +def _filters_out_children_files(files_to_upgrade: t.List[Path]) -> t.List[Path]: """ Filters out children paths of "input" if "input" is already in the list. Args: @@ -237,7 +236,7 @@ def _filters_out_children_files(files_to_upgrade: List[Path]) -> List[Path]: return files_to_upgrade -def _replace_safely_original_files(files_to_replace: List[Path], study_path: Path, tmp_path: Path) -> None: +def _replace_safely_original_files(files_to_replace: t.List[Path], study_path: Path, tmp_path: Path) -> None: """ Replace files/folders of the study that should be upgraded by their copy already upgraded in the tmp directory. It uses Path.rename() and an intermediary tmp directory to swap the folders safely. @@ -286,6 +285,5 @@ def should_study_be_denormalized(src_version: str, target_version: str) -> bool: if curr_version == old and curr_version != target_version: list_of_upgrades.append(new) curr_version = new - # For now, the only upgrade that impacts study matrices is the upgrade from v8.1 to v8.2 - # In a near future, the upgrade from v8.6 to v8.7 will also require denormalization - return "820" in list_of_upgrades + # These upgrades alter matrices so the study needs to be denormalized + return "820" in list_of_upgrades or "870" in list_of_upgrades diff --git a/antarest/study/storage/study_upgrader/upgrader_860.py b/antarest/study/storage/study_upgrader/upgrader_860.py index 23ea05f178..4d6f873f0d 100644 --- a/antarest/study/storage/study_upgrader/upgrader_860.py +++ b/antarest/study/storage/study_upgrader/upgrader_860.py @@ -10,6 +10,16 @@ def upgrade_860(study_path: Path) -> None: + """ + Upgrade the study configuration to version 860. + + NOTE: + The file `study.antares` is not upgraded here. + + Args: + study_path: path to the study directory. + """ + reader = IniReader(DUPLICATE_KEYS) data = reader.read(study_path / GENERAL_DATA_PATH) data["adequacy patch"]["enable-first-step "] = True diff --git a/antarest/study/storage/study_upgrader/upgrader_870.py b/antarest/study/storage/study_upgrader/upgrader_870.py new file mode 100644 index 0000000000..9b67a77c52 --- /dev/null +++ b/antarest/study/storage/study_upgrader/upgrader_870.py @@ -0,0 +1,64 @@ +import typing as t +from pathlib import Path + +import numpy as np +import numpy.typing as npt +import pandas as pd + +from antarest.study.storage.rawstudy.ini_reader import IniReader +from antarest.study.storage.rawstudy.ini_writer import IniWriter + + +# noinspection SpellCheckingInspection +def upgrade_870(study_path: Path) -> None: + """ + Upgrade the study configuration to version 870. + + NOTE: + The file `study.antares` is not upgraded here. + + Args: + study_path: path to the study directory. + """ + + # Split existing binding constraints in 3 different files + binding_constraints_path = study_path / "input" / "bindingconstraints" + binding_constraints_files = binding_constraints_path.glob("*.txt") + for file in binding_constraints_files: + name = file.stem + if file.stat().st_size == 0: + lt, gt, eq = pd.Series(), pd.Series(), pd.Series() + else: + df = pd.read_csv(file, sep="\t", header=None) + lt, gt, eq = df.iloc[:, 0], df.iloc[:, 1], df.iloc[:, 2] + for term, suffix in zip([lt, gt, eq], ["lt", "gt", "eq"]): + # noinspection PyTypeChecker + np.savetxt( + binding_constraints_path / f"{name}_{suffix}.txt", + t.cast(npt.NDArray[np.float64], term.values), + delimiter="\t", + fmt="%.6f", + ) + file.unlink() + + # Add property group for every section in .ini file + ini_file_path = binding_constraints_path / "bindingconstraints.ini" + data = IniReader().read(ini_file_path) + for section in data: + data[section]["group"] = "default" + IniWriter().write(data, ini_file_path) + + # Add properties for thermal clusters in .ini file + ini_files = study_path.glob("input/thermal/clusters/*/list.ini") + thermal_path = study_path / Path("input/thermal/series") + for ini_file_path in ini_files: + data = IniReader().read(ini_file_path) + area_id = ini_file_path.parent.name + for cluster in data: + new_thermal_path = thermal_path / area_id / cluster.lower() + (new_thermal_path / "CO2Cost.txt").touch() + (new_thermal_path / "fuelCost.txt").touch() + data[cluster]["costgeneration"] = "SetManually" + data[cluster]["efficiency"] = 100 + data[cluster]["variableomcost"] = 0 + IniWriter().write(data, ini_file_path) diff --git a/antarest/study/storage/study_upgrader/upgrader_880.py b/antarest/study/storage/study_upgrader/upgrader_880.py new file mode 100644 index 0000000000..0de50cff4b --- /dev/null +++ b/antarest/study/storage/study_upgrader/upgrader_880.py @@ -0,0 +1,32 @@ +import glob +from pathlib import Path + +from antarest.study.storage.rawstudy.ini_reader import IniReader +from antarest.study.storage.rawstudy.ini_writer import IniWriter +from antarest.study.storage.rawstudy.model.filesystem.root.settings.generaldata import DUPLICATE_KEYS + + +# noinspection SpellCheckingInspection +def upgrade_880(study_path: Path) -> None: + """ + Upgrade the study configuration to version 880. + + NOTE: + The file `study.antares` is not upgraded here. + + Args: + study_path: path to the study directory. + """ + st_storage_path = study_path / "input" / "st-storage" / "clusters" + if not st_storage_path.exists(): + # The folder only exists for studies in v8.6+ that have some short term storage clusters. + # For every other case, this upgrader has nothing to do. + return + writer = IniWriter(special_keys=DUPLICATE_KEYS) + cluster_files = glob.glob(str(st_storage_path / "*" / "list.ini")) + for file in cluster_files: + file_path = Path(file) + cluster_list = IniReader().read(file_path) + for cluster in cluster_list: + cluster_list[cluster]["enabled"] = True + writer.write(cluster_list, file_path) diff --git a/antarest/study/storage/utils.py b/antarest/study/storage/utils.py index 8e9a9a573d..5dc97b081b 100644 --- a/antarest/study/storage/utils.py +++ b/antarest/study/storage/utils.py @@ -243,30 +243,9 @@ def assert_permission( MATRIX_INPUT_DAYS_COUNT = 365 -MONTHS = ( - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December", -) +MONTHS = calendar.month_name[1:] -DAY_NAMES = ( - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", - "Sunday", -) +DAY_NAMES = calendar.day_name[:] def get_start_date( @@ -293,7 +272,7 @@ def get_start_date( starting_month_index = MONTHS.index(starting_month.title()) + 1 starting_day_index = DAY_NAMES.index(starting_day.title()) - target_year = 2000 + target_year = 2018 while True: if leapyear == calendar.isleap(target_year): first_day = datetime(target_year, starting_month_index, 1) diff --git a/antarest/study/storage/variantstudy/business/command_extractor.py b/antarest/study/storage/variantstudy/business/command_extractor.py index 9aa5a9b397..4ac5070a69 100644 --- a/antarest/study/storage/variantstudy/business/command_extractor.py +++ b/antarest/study/storage/variantstudy/business/command_extractor.py @@ -1,6 +1,6 @@ import base64 import logging -from typing import List, Optional, Tuple, cast +import typing as t import numpy as np @@ -9,13 +9,11 @@ from antarest.matrixstore.model import MatrixData from antarest.matrixstore.service import ISimpleMatrixService from antarest.study.storage.patch_service import PatchService -from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import BindingConstraintFrequency from antarest.study.storage.rawstudy.model.filesystem.config.files import get_playlist from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy from antarest.study.storage.rawstudy.model.filesystem.root.filestudytree import FileStudyTree from antarest.study.storage.variantstudy.business.matrix_constants_generator import GeneratorMatrixConstants from antarest.study.storage.variantstudy.business.utils import strip_matrix_protocol -from antarest.study.storage.variantstudy.model.command.common import BindingConstraintOperator from antarest.study.storage.variantstudy.model.command.create_area import CreateArea from antarest.study.storage.variantstudy.model.command.create_binding_constraint import CreateBindingConstraint from antarest.study.storage.variantstudy.model.command.create_cluster import CreateCluster @@ -40,7 +38,7 @@ def _find_binding_config(binding_id: str, study_tree: FileStudyTree) -> JSON: url = ["input", "bindingconstraints", "bindingconstraints"] for binding_config in study_tree.get(url).values(): if binding_config["id"] == binding_id: - return cast(JSON, binding_config) + return t.cast(JSON, binding_config) raise ValueError(f"Binding constraint '{binding_id}' not found in '{''.join(url)}'") @@ -56,7 +54,7 @@ def __init__(self, matrix_service: ISimpleMatrixService, patch_service: PatchSer patch_service=self.patch_service, ) - def extract_area(self, study: FileStudy, area_id: str) -> Tuple[List[ICommand], List[ICommand]]: + def extract_area(self, study: FileStudy, area_id: str) -> t.Tuple[t.List[ICommand], t.List[ICommand]]: stopwatch = StopWatch() study_tree = study.tree study_config = study.config @@ -64,7 +62,7 @@ def extract_area(self, study: FileStudy, area_id: str) -> Tuple[List[ICommand], optimization_data = study_tree.get(["input", "areas", area_id, "optimization"]) ui_data = study_tree.get(["input", "areas", area_id, "ui"]) - study_commands: List[ICommand] = [ + study_commands: t.List[ICommand] = [ CreateArea( area_name=area.name, command_context=self.command_context, @@ -83,7 +81,7 @@ def extract_area(self, study: FileStudy, area_id: str) -> Tuple[List[ICommand], stopwatch.log_elapsed(lambda x: logger.info(f"Area command extraction done in {x}s")) links_data = study_tree.get(["input", "links", area_id, "properties"]) - links_commands: List[ICommand] = [] + links_commands: t.List[ICommand] = [] for link in area.links: links_commands += self.extract_link(study, area_id, link, links_data) @@ -142,8 +140,8 @@ def extract_link( study: FileStudy, area1: str, area2: str, - links_data: Optional[JSON] = None, - ) -> List[ICommand]: + links_data: t.Optional[JSON] = None, + ) -> t.List[ICommand]: study_tree = study.tree link_command = CreateLink( area1=area1, @@ -162,7 +160,7 @@ def extract_link( command_context=self.command_context, ) null_matrix_id = strip_matrix_protocol(self.generator_matrix_constants.get_null_matrix()) - commands: List[ICommand] = [link_command, link_config_command] + commands: t.List[ICommand] = [link_command, link_config_command] if study.config.version < 820: commands.append( self.generate_replace_matrix( @@ -193,7 +191,7 @@ def extract_link( ) return commands - def _extract_cluster(self, study: FileStudy, area_id: str, cluster_id: str, renewables: bool) -> List[ICommand]: + def _extract_cluster(self, study: FileStudy, area_id: str, cluster_id: str, renewables: bool) -> t.List[ICommand]: study_tree = study.tree if renewables: cluster_type = "renewables" # with a final "s" @@ -209,7 +207,7 @@ def _extract_cluster(self, study: FileStudy, area_id: str, cluster_id: str, rene null_matrix_id = strip_matrix_protocol(self.generator_matrix_constants.get_null_matrix()) # Note that cluster IDs are case-insensitive, but series IDs are in lower case. series_id = cluster_id.lower() - study_commands: List[ICommand] = [ + study_commands: t.List[ICommand] = [ create_cluster_command( area_id=area_id, cluster_name=cluster.id, @@ -239,13 +237,13 @@ def _extract_cluster(self, study: FileStudy, area_id: str, cluster_id: str, rene ) return study_commands - def extract_cluster(self, study: FileStudy, area_id: str, thermal_id: str) -> List[ICommand]: + def extract_cluster(self, study: FileStudy, area_id: str, thermal_id: str) -> t.List[ICommand]: return self._extract_cluster(study, area_id, thermal_id, False) - def extract_renewables_cluster(self, study: FileStudy, area_id: str, renewables_id: str) -> List[ICommand]: + def extract_renewables_cluster(self, study: FileStudy, area_id: str, renewables_id: str) -> t.List[ICommand]: return self._extract_cluster(study, area_id, renewables_id, True) - def extract_hydro(self, study: FileStudy, area_id: str) -> List[ICommand]: + def extract_hydro(self, study: FileStudy, area_id: str) -> t.List[ICommand]: study_tree = study.tree commands = [ self.generate_replace_matrix( @@ -306,8 +304,8 @@ def extract_hydro(self, study: FileStudy, area_id: str) -> List[ICommand]: return commands - def extract_district(self, study: FileStudy, district_id: str) -> List[ICommand]: - study_commands: List[ICommand] = [] + def extract_district(self, study: FileStudy, district_id: str) -> t.List[ICommand]: + study_commands: t.List[ICommand] = [] study_config = study.config study_tree = study.tree district_config = study_config.sets[district_id] @@ -325,64 +323,66 @@ def extract_district(self, study: FileStudy, district_id: str) -> List[ICommand] ) return study_commands - def extract_comments(self, study: FileStudy) -> List[ICommand]: + def extract_comments(self, study: FileStudy) -> t.List[ICommand]: study_tree = study.tree - content = cast(bytes, study_tree.get(["settings", "comments"])) + content = t.cast(bytes, study_tree.get(["settings", "comments"])) comments = content.decode("utf-8") - return [ - UpdateComments( - comments=comments, - command_context=self.command_context, - ) - ] + return [UpdateComments(comments=comments, command_context=self.command_context)] def extract_binding_constraint( self, study: FileStudy, binding_id: str, - bindings_data: Optional[JSON] = None, - ) -> List[ICommand]: + bindings_data: t.Optional[JSON] = None, + ) -> t.List[ICommand]: study_tree = study.tree + + # Retrieve binding constraint properties from the study tree, + # so, field names follow the same convention as the INI file. binding: JSON = _find_binding_config(binding_id, study_tree) if bindings_data is None else bindings_data - binding_constraint_command = CreateBindingConstraint( - name=binding["name"], - enabled=binding["enabled"], - time_step=BindingConstraintFrequency(binding["type"]), - operator=BindingConstraintOperator(binding["operator"]), - coeffs={ - coeff: [float(el) for el in str(value).split("%")] - for coeff, value in binding.items() - if "%" in coeff or "." in coeff - }, - comments=binding.get("comments", None), - command_context=self.command_context, - ) - study_commands: List[ICommand] = [ - binding_constraint_command, - self.generate_replace_matrix( - study_tree, - ["input", "bindingconstraints", binding["id"]], - ), - ] - return study_commands - def generate_update_config( - self, - study_tree: FileStudyTree, - url: List[str], - ) -> ICommand: + # Extract the binding constraint ID, which is recalculated from the name in the command + bc_id = binding.pop("id") + + # Extract binding constraint terms, which keys contain "%" or "." + terms = {} + for term_id, value in sorted(binding.items()): + if "%" in term_id or "." in term_id: + weight, _, offset = str(value).partition("%") + term_value = [float(weight), int(offset)] if offset else [float(weight)] + terms[term_id] = term_value + del binding[term_id] + + # Extract the matrices associated with the binding constraint + if study.config.version < 870: + urls = {"values": ["input", "bindingconstraints", bc_id]} + else: + urls = { + "less_term_matrix": ["input", "bindingconstraints", f"{bc_id}_lt"], + "greater_term_matrix": ["input", "bindingconstraints", f"{bc_id}_gt"], + "equal_term_matrix": ["input", "bindingconstraints", f"{bc_id}_eq"], + } + + matrices: t.Dict[str, t.List[t.List[float]]] = {} + for name, url in urls.items(): + matrix = study_tree.get(url) + if matrix is not None: + matrices[name] = matrix["data"] + + # Create the command to create the binding constraint + create_cmd = CreateBindingConstraint(**binding, **matrices, coeffs=terms, command_context=self.command_context) + + return [create_cmd] + + def generate_update_config(self, study_tree: FileStudyTree, url: t.List[str]) -> ICommand: data = study_tree.get(url) - return UpdateConfig( - target="/".join(url), - data=data, - command_context=self.command_context, - ) + return UpdateConfig(target="/".join(url), data=data, command_context=self.command_context) - def generate_update_rawfile(self, study_tree: FileStudyTree, url: List[str]) -> ICommand: + def generate_update_raw_file(self, study_tree: FileStudyTree, url: t.List[str]) -> ICommand: data = study_tree.get(url) return UpdateRawFile( target="/".join(url), - b64Data=base64.b64encode(cast(bytes, data)).decode("utf-8"), + b64Data=base64.b64encode(t.cast(bytes, data)).decode("utf-8"), command_context=self.command_context, ) @@ -390,7 +390,7 @@ def generate_update_comments( self, study_tree: FileStudyTree, ) -> ICommand: - content = cast(bytes, study_tree.get(["settings", "comments"])) + content = t.cast(bytes, study_tree.get(["settings", "comments"])) comments = content.decode("utf-8") return UpdateComments( comments=comments, @@ -414,8 +414,8 @@ def generate_update_playlist( def generate_replace_matrix( self, study_tree: FileStudyTree, - url: List[str], - default_value: Optional[str] = None, + url: t.List[str], + default_value: t.Optional[str] = None, ) -> ICommand: data = study_tree.get(url) if isinstance(data, str): @@ -425,7 +425,7 @@ def generate_replace_matrix( else: matrix = [[]] if default_value is None else default_value if isinstance(matrix, np.ndarray): - matrix = cast(List[List[MatrixData]], matrix.tolist()) + matrix = t.cast(t.List[t.List[MatrixData]], matrix.tolist()) return ReplaceMatrix( target="/".join(url), matrix=matrix, diff --git a/antarest/study/storage/variantstudy/business/command_reverter.py b/antarest/study/storage/variantstudy/business/command_reverter.py index 1ac83c2704..089589576f 100644 --- a/antarest/study/storage/variantstudy/business/command_reverter.py +++ b/antarest/study/storage/variantstudy/business/command_reverter.py @@ -1,14 +1,16 @@ import logging +import typing as t from pathlib import Path -from typing import Callable, Dict, List from antarest.study.storage.rawstudy.model.filesystem.config.model import transform_name_to_id from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy from antarest.study.storage.rawstudy.model.filesystem.folder_node import ChildNotFoundError -from antarest.study.storage.variantstudy.business.utils import strip_matrix_protocol from antarest.study.storage.variantstudy.model.command.common import CommandName from antarest.study.storage.variantstudy.model.command.create_area import CreateArea -from antarest.study.storage.variantstudy.model.command.create_binding_constraint import CreateBindingConstraint +from antarest.study.storage.variantstudy.model.command.create_binding_constraint import ( + TERM_MATRICES, + CreateBindingConstraint, +) from antarest.study.storage.variantstudy.model.command.create_cluster import CreateCluster from antarest.study.storage.variantstudy.model.command.create_district import CreateDistrict from antarest.study.storage.variantstudy.model.command.create_link import CreateLink @@ -36,39 +38,39 @@ class CommandReverter: def __init__(self) -> None: - self.method_dict: Dict[ + self.method_dict: t.Dict[ CommandName, - Callable[[ICommand, List[ICommand], FileStudy], List[ICommand]], + t.Callable[[ICommand, t.List[ICommand], FileStudy], t.List[ICommand]], ] = {command_name: getattr(self, f"_revert_{command_name.value}") for command_name in CommandName} @staticmethod - def _revert_create_area(base_command: CreateArea, history: List["ICommand"], base: FileStudy) -> List[ICommand]: + def _revert_create_area(base_command: CreateArea, history: t.List["ICommand"], base: FileStudy) -> t.List[ICommand]: area_id = transform_name_to_id(base_command.area_name) return [RemoveArea(id=area_id, command_context=base_command.command_context)] @staticmethod - def _revert_remove_area(base_command: RemoveArea, history: List["ICommand"], base: FileStudy) -> List[ICommand]: + def _revert_remove_area(base_command: RemoveArea, history: t.List["ICommand"], base: FileStudy) -> t.List[ICommand]: raise NotImplementedError("The revert function for RemoveArea is not available") @staticmethod def _revert_create_district( base_command: CreateDistrict, - history: List["ICommand"], + history: t.List["ICommand"], base: FileStudy, - ) -> List[ICommand]: + ) -> t.List[ICommand]: district_id = transform_name_to_id(base_command.name) return [RemoveDistrict(id=district_id, command_context=base_command.command_context)] @staticmethod def _revert_remove_district( base_command: RemoveDistrict, - history: List["ICommand"], + history: t.List["ICommand"], base: FileStudy, - ) -> List[ICommand]: + ) -> t.List[ICommand]: raise NotImplementedError("The revert function for RemoveDistrict is not available") @staticmethod - def _revert_create_link(base_command: CreateLink, history: List["ICommand"], base: FileStudy) -> List[ICommand]: + def _revert_create_link(base_command: CreateLink, history: t.List["ICommand"], base: FileStudy) -> t.List[ICommand]: return [ RemoveLink( area1=base_command.area1, @@ -78,66 +80,71 @@ def _revert_create_link(base_command: CreateLink, history: List["ICommand"], bas ] @staticmethod - def _revert_remove_link(base_command: RemoveLink, history: List["ICommand"], base: FileStudy) -> List[ICommand]: + def _revert_remove_link(base_command: RemoveLink, history: t.List["ICommand"], base: FileStudy) -> t.List[ICommand]: raise NotImplementedError("The revert function for RemoveLink is not available") @staticmethod def _revert_create_binding_constraint( base_command: CreateBindingConstraint, - history: List["ICommand"], + history: t.List["ICommand"], base: FileStudy, - ) -> List[ICommand]: + ) -> t.List[ICommand]: bind_id = transform_name_to_id(base_command.name) return [RemoveBindingConstraint(id=bind_id, command_context=base_command.command_context)] @staticmethod def _revert_update_binding_constraint( base_command: UpdateBindingConstraint, - history: List["ICommand"], + history: t.List["ICommand"], base: FileStudy, - ) -> List[ICommand]: + ) -> t.List[ICommand]: for command in reversed(history): if isinstance(command, UpdateBindingConstraint) and command.id == base_command.id: return [command] elif isinstance(command, CreateBindingConstraint) and transform_name_to_id(command.name) == base_command.id: - return [ - UpdateBindingConstraint( - id=base_command.id, - enabled=command.enabled, - time_step=command.time_step, - operator=command.operator, - coeffs=command.coeffs, - values=strip_matrix_protocol(command.values), - filter_year_by_year=command.filter_year_by_year, - filter_synthesis=command.filter_synthesis, - comments=command.comments, - command_context=command.command_context, - ) - ] + args = { + "id": base_command.id, + "enabled": command.enabled, + "time_step": command.time_step, + "operator": command.operator, + "coeffs": command.coeffs, + "filter_year_by_year": command.filter_year_by_year, + "filter_synthesis": command.filter_synthesis, + "comments": command.comments, + "command_context": command.command_context, + } + + matrix_service = command.command_context.matrix_service + for matrix_name in ["values"] + TERM_MATRICES: + matrix = getattr(command, matrix_name) + if matrix is not None: + args[matrix_name] = matrix_service.get_matrix_id(matrix) + + return [UpdateBindingConstraint(**args)] return base_command.get_command_extractor().extract_binding_constraint(base, base_command.id) @staticmethod def _revert_remove_binding_constraint( base_command: RemoveBindingConstraint, - history: List["ICommand"], + history: t.List["ICommand"], base: FileStudy, - ) -> List[ICommand]: + ) -> t.List[ICommand]: raise NotImplementedError("The revert function for RemoveBindingConstraint is not available") @staticmethod def _revert_update_scenario_builder( base_command: UpdateScenarioBuilder, - history: List["ICommand"], + history: t.List["ICommand"], base: FileStudy, - ) -> List[ICommand]: + ) -> t.List[ICommand]: # todo make the diff between base study scenariobuilder data and base_command raise NotImplementedError("The revert function for UpdateScenarioBuilder is not available") @staticmethod def _revert_create_cluster( - base_command: CreateCluster, history: List["ICommand"], base: FileStudy - ) -> List[ICommand]: + base_command: CreateCluster, history: t.List["ICommand"], base: FileStudy + ) -> t.List[ICommand]: cluster_id = transform_name_to_id(base_command.cluster_name) return [ RemoveCluster( @@ -149,16 +156,16 @@ def _revert_create_cluster( @staticmethod def _revert_remove_cluster( - base_command: RemoveCluster, history: List["ICommand"], base: FileStudy - ) -> List[ICommand]: + base_command: RemoveCluster, history: t.List["ICommand"], base: FileStudy + ) -> t.List[ICommand]: raise NotImplementedError("The revert function for RemoveCluster is not available") @staticmethod def _revert_create_renewables_cluster( base_command: CreateRenewablesCluster, - history: List["ICommand"], + history: t.List["ICommand"], base: FileStudy, - ) -> List[ICommand]: + ) -> t.List[ICommand]: cluster_id = transform_name_to_id(base_command.cluster_name) return [ RemoveRenewablesCluster( @@ -171,17 +178,17 @@ def _revert_create_renewables_cluster( @staticmethod def _revert_remove_renewables_cluster( base_command: RemoveRenewablesCluster, - history: List["ICommand"], + history: t.List["ICommand"], base: FileStudy, - ) -> List[ICommand]: + ) -> t.List[ICommand]: raise NotImplementedError("The revert function for RemoveRenewablesCluster is not available") @staticmethod def _revert_create_st_storage( base_command: CreateSTStorage, - history: List["ICommand"], + history: t.List["ICommand"], base: FileStudy, - ) -> List[ICommand]: + ) -> t.List[ICommand]: storage_id = base_command.parameters.id return [ RemoveSTStorage( @@ -194,15 +201,15 @@ def _revert_create_st_storage( @staticmethod def _revert_remove_st_storage( base_command: RemoveSTStorage, - history: List["ICommand"], + history: t.List["ICommand"], base: FileStudy, - ) -> List[ICommand]: + ) -> t.List[ICommand]: raise NotImplementedError("The revert function for RemoveSTStorage is not available") @staticmethod def _revert_replace_matrix( - base_command: ReplaceMatrix, history: List["ICommand"], base: FileStudy - ) -> List[ICommand]: + base_command: ReplaceMatrix, history: t.List["ICommand"], base: FileStudy + ) -> t.List[ICommand]: for command in reversed(history): if isinstance(command, ReplaceMatrix) and command.target == base_command.target: return [command] @@ -215,8 +222,10 @@ def _revert_replace_matrix( return [] # if the matrix does not exist, there is nothing to revert @staticmethod - def _revert_update_config(base_command: UpdateConfig, history: List["ICommand"], base: FileStudy) -> List[ICommand]: - update_config_list: List[UpdateConfig] = [] + def _revert_update_config( + base_command: UpdateConfig, history: t.List["ICommand"], base: FileStudy + ) -> t.List[ICommand]: + update_config_list: t.List[UpdateConfig] = [] self_target_path = Path(base_command.target) parent_path: Path = Path("../model/command") for command in reversed(history): @@ -230,7 +239,7 @@ def _revert_update_config(base_command: UpdateConfig, history: List["ICommand"], parent_path = Path(command.target) break - output_list: List[ICommand] = [ + output_list: t.List[ICommand] = [ command for command in update_config_list[::-1] if parent_path in Path(command.target).parents or str(parent_path) == command.target @@ -253,9 +262,9 @@ def _revert_update_config(base_command: UpdateConfig, history: List["ICommand"], @staticmethod def _revert_update_comments( base_command: UpdateComments, - history: List["ICommand"], + history: t.List["ICommand"], base: FileStudy, - ) -> List[ICommand]: + ) -> t.List[ICommand]: for command in reversed(history): if isinstance(command, UpdateComments): return [command] @@ -268,9 +277,9 @@ def _revert_update_comments( @staticmethod def _revert_update_playlist( base_command: UpdatePlaylist, - history: List["ICommand"], + history: t.List["ICommand"], base: FileStudy, - ) -> List[ICommand]: + ) -> t.List[ICommand]: for command in reversed(history): if isinstance(command, UpdatePlaylist): return [command] @@ -281,33 +290,39 @@ def _revert_update_playlist( return [] # if the file does not exist, there is nothing to revert @staticmethod - def _revert_update_file(base_command: UpdateRawFile, history: List["ICommand"], base: FileStudy) -> List[ICommand]: + def _revert_update_file( + base_command: UpdateRawFile, history: t.List["ICommand"], base: FileStudy + ) -> t.List[ICommand]: for command in reversed(history): if isinstance(command, UpdateRawFile) and command.target == base_command.target: return [command] - return [base_command.get_command_extractor().generate_update_rawfile(base.tree, base_command.target.split("/"))] + extractor = base_command.get_command_extractor() + return [extractor.generate_update_raw_file(base.tree, base_command.target.split("/"))] @staticmethod def _revert_update_district( base_command: UpdateDistrict, - history: List["ICommand"], + history: t.List["ICommand"], base: FileStudy, - ) -> List[ICommand]: + ) -> t.List[ICommand]: for command in reversed(history): - if isinstance(command, UpdateDistrict) and command.id == base_command.id: - return [command] - elif isinstance(command, CreateDistrict) and transform_name_to_id(command.name) == base_command.id: + # fmt: off + if ( + (isinstance(command, UpdateDistrict) and command.id == base_command.id) or + (isinstance(command, CreateDistrict) and transform_name_to_id(command.name) == base_command.id) + ): return [command] - return [base_command.get_command_extractor().generate_update_district(base, base_command.id)] + extractor = base_command.get_command_extractor() + return [extractor.generate_update_district(base, base_command.id)] def revert( self, base_command: ICommand, - history: List["ICommand"], + history: t.List["ICommand"], base: FileStudy, - ) -> List[ICommand]: + ) -> t.List[ICommand]: """ Generate a list of commands to revert the given command. diff --git a/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/__init__.py b/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/__init__.py index 0a1b9046e5..679232c20b 100644 --- a/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/__init__.py +++ b/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/__init__.py @@ -1 +1 @@ -from . import series +from . import series_after_v87, series_before_v87 # noqa: F401 diff --git a/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/series_after_v87.py b/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/series_after_v87.py new file mode 100644 index 0000000000..30c23a7dfe --- /dev/null +++ b/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/series_after_v87.py @@ -0,0 +1,7 @@ +import numpy as np + +default_bc_hourly = np.zeros((8784, 1), dtype=np.float64) +default_bc_hourly.flags.writeable = False + +default_bc_weekly_daily = np.zeros((366, 1), dtype=np.float64) +default_bc_weekly_daily.flags.writeable = False diff --git a/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/series.py b/antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/series_before_v87.py similarity index 100% rename from antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/series.py rename to antarest/study/storage/variantstudy/business/matrix_constants/binding_constraint/series_before_v87.py diff --git a/antarest/study/storage/variantstudy/business/matrix_constants_generator.py b/antarest/study/storage/variantstudy/business/matrix_constants_generator.py index 6a4dc233d4..4c75f6a6eb 100644 --- a/antarest/study/storage/variantstudy/business/matrix_constants_generator.py +++ b/antarest/study/storage/variantstudy/business/matrix_constants_generator.py @@ -35,11 +35,11 @@ ONES_SCENARIO_MATRIX = "ones_scenario_matrix" # Binding constraint aliases -BINDING_CONSTRAINT_HOURLY = "empty_2nd_member_hourly" -"""2D-matrix of shape (8784, 3), filled-in with zeros for hourly binding constraints.""" +BINDING_CONSTRAINT_HOURLY_v86 = "empty_2nd_member_hourly_v86" +BINDING_CONSTRAINT_DAILY_WEEKLY_v86 = "empty_2nd_member_daily_or_weekly_v86" -BINDING_CONSTRAINT_WEEKLY_DAILY = "empty_2nd_member_weekly_daily" -"""2D-matrix of shape (366, 3), filled-in with zeros for weekly/daily binding constraints.""" +BINDING_CONSTRAINT_HOURLY_v87 = "empty_2nd_member_hourly_v87" +BINDING_CONSTRAINT_DAILY_WEEKLY_v87 = "empty_2nd_member_daily_or_weekly_v87" # Short-term storage aliases ST_STORAGE_PMAX_INJECTION = ONES_SCENARIO_MATRIX @@ -95,15 +95,23 @@ def init_constant_matrices( self.hashes[RESERVES_TS] = self.matrix_service.create(FIXED_4_COLUMNS) self.hashes[MISCGEN_TS] = self.matrix_service.create(FIXED_8_COLUMNS) - # Binding constraint matrices - series = matrix_constants.binding_constraint.series - self.hashes[BINDING_CONSTRAINT_HOURLY] = self.matrix_service.create(series.default_bc_hourly) - self.hashes[BINDING_CONSTRAINT_WEEKLY_DAILY] = self.matrix_service.create(series.default_bc_weekly_daily) + # Binding constraint matrices + series_before_87 = matrix_constants.binding_constraint.series_before_v87 + self.hashes[BINDING_CONSTRAINT_HOURLY_v86] = self.matrix_service.create(series_before_87.default_bc_hourly) + self.hashes[BINDING_CONSTRAINT_DAILY_WEEKLY_v86] = self.matrix_service.create( + series_before_87.default_bc_weekly_daily + ) - # Some short-term storage matrices use np.ones((8760, 1)) - self.hashes[ONES_SCENARIO_MATRIX] = self.matrix_service.create( - matrix_constants.st_storage.series.pmax_injection - ) + series_after_87 = matrix_constants.binding_constraint.series_after_v87 + self.hashes[BINDING_CONSTRAINT_HOURLY_v87] = self.matrix_service.create(series_after_87.default_bc_hourly) + self.hashes[BINDING_CONSTRAINT_DAILY_WEEKLY_v87] = self.matrix_service.create( + series_after_87.default_bc_weekly_daily + ) + + # Some short-term storage matrices use np.ones((8760, 1)) + self.hashes[ONES_SCENARIO_MATRIX] = self.matrix_service.create( + matrix_constants.st_storage.series.pmax_injection + ) def get_hydro_max_power(self, version: int) -> str: if version > 650: @@ -157,17 +165,21 @@ def get_default_reserves(self) -> str: def get_default_miscgen(self) -> str: return MATRIX_PROTOCOL_PREFIX + self.hashes[MISCGEN_TS] - def get_binding_constraint_hourly(self) -> str: + def get_binding_constraint_hourly_86(self) -> str: """2D-matrix of shape (8784, 3), filled-in with zeros.""" - return MATRIX_PROTOCOL_PREFIX + self.hashes[BINDING_CONSTRAINT_HOURLY] + return MATRIX_PROTOCOL_PREFIX + self.hashes[BINDING_CONSTRAINT_HOURLY_v86] - def get_binding_constraint_daily(self) -> str: + def get_binding_constraint_daily_weekly_86(self) -> str: """2D-matrix of shape (366, 3), filled-in with zeros.""" - return MATRIX_PROTOCOL_PREFIX + self.hashes[BINDING_CONSTRAINT_WEEKLY_DAILY] + return MATRIX_PROTOCOL_PREFIX + self.hashes[BINDING_CONSTRAINT_DAILY_WEEKLY_v86] + + def get_binding_constraint_hourly_87(self) -> str: + """2D-matrix of shape (8784, 1), filled-in with zeros.""" + return MATRIX_PROTOCOL_PREFIX + self.hashes[BINDING_CONSTRAINT_HOURLY_v87] - def get_binding_constraint_weekly(self) -> str: - """2D-matrix of shape (366, 3), filled-in with zeros, same as daily.""" - return MATRIX_PROTOCOL_PREFIX + self.hashes[BINDING_CONSTRAINT_WEEKLY_DAILY] + def get_binding_constraint_daily_weekly_87(self) -> str: + """2D-matrix of shape (8784, 1), filled-in with zeros.""" + return MATRIX_PROTOCOL_PREFIX + self.hashes[BINDING_CONSTRAINT_DAILY_WEEKLY_v87] def get_st_storage_pmax_injection(self) -> str: """2D-matrix of shape (8760, 1), filled-in with ones.""" diff --git a/antarest/study/storage/variantstudy/business/utils.py b/antarest/study/storage/variantstudy/business/utils.py index 933c72bed7..75396ccbc6 100644 --- a/antarest/study/storage/variantstudy/business/utils.py +++ b/antarest/study/storage/variantstudy/business/utils.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Optional, Sequence, Union +import typing as t from antarest.core.model import JSON from antarest.matrixstore.model import MatrixData @@ -9,7 +9,7 @@ from antarest.study.storage.variantstudy.model.model import CommandDTO -def validate_matrix(matrix: Union[List[List[MatrixData]], str], values: Dict[str, Any]) -> str: +def validate_matrix(matrix: t.Union[t.List[t.List[MatrixData]], str], values: t.Dict[str, t.Any]) -> str: """ Validates the matrix, stores the matrix array in the matrices repository, and returns a reference to the stored array. @@ -62,7 +62,7 @@ def remove_none_args(command_dto: CommandDTO) -> CommandDTO: return command_dto -def strip_matrix_protocol(matrix_uri: Union[List[List[float]], str, None]) -> str: +def strip_matrix_protocol(matrix_uri: t.Union[t.List[t.List[float]], str, None]) -> str: assert isinstance(matrix_uri, str) if matrix_uri.startswith(MATRIX_PROTOCOL_PREFIX): return matrix_uri[len(MATRIX_PROTOCOL_PREFIX) :] @@ -89,13 +89,13 @@ def decode(alias: str, study: FileStudy) -> str: def transform_command_to_dto( - commands: Sequence[ICommand], - ref_commands: Optional[Sequence[CommandDTO]] = None, + commands: t.Sequence[ICommand], + ref_commands: t.Optional[t.Sequence[CommandDTO]] = None, force_aggregate: bool = False, -) -> List[CommandDTO]: +) -> t.List[CommandDTO]: if len(commands) <= 1: return [command.to_dto() for command in commands] - commands_dto: List[CommandDTO] = [] + commands_dto: t.List[CommandDTO] = [] ref_commands_dto = ref_commands if ref_commands is not None else [command.to_dto() for command in commands] prev_command = commands[0] cur_dto_index = 0 diff --git a/antarest/study/storage/variantstudy/business/utils_binding_constraint.py b/antarest/study/storage/variantstudy/business/utils_binding_constraint.py index f1ef937cdf..ebbeeec739 100644 --- a/antarest/study/storage/variantstudy/business/utils_binding_constraint.py +++ b/antarest/study/storage/variantstudy/business/utils_binding_constraint.py @@ -1,89 +1,13 @@ -from typing import Dict, List, Literal, Mapping, Optional, Sequence, Union +import typing as t -from antarest.core.model import JSON -from antarest.matrixstore.model import MatrixData -from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import ( - BindingConstraintDTO, - BindingConstraintFrequency, -) -from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig -from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy -from antarest.study.storage.variantstudy.model.command.common import BindingConstraintOperator, CommandOutput - - -def apply_binding_constraint( - study_data: FileStudy, - binding_constraints: JSON, - new_key: str, - bd_id: str, - name: str, - comments: Optional[str], - enabled: bool, - freq: BindingConstraintFrequency, - operator: BindingConstraintOperator, - coeffs: Dict[str, List[float]], - values: Optional[Union[List[List[MatrixData]], str]], - filter_year_by_year: Optional[str] = None, - filter_synthesis: Optional[str] = None, -) -> CommandOutput: - binding_constraints[new_key] = { - "name": name, - "id": bd_id, - "enabled": enabled, - "type": freq.value, - "operator": operator.value, - } - if study_data.config.version >= 830: - if filter_year_by_year: - binding_constraints[new_key]["filter-year-by-year"] = filter_year_by_year - if filter_synthesis: - binding_constraints[new_key]["filter-synthesis"] = filter_synthesis - if comments is not None: - binding_constraints[new_key]["comments"] = comments - - for link_or_cluster in coeffs: - if "%" in link_or_cluster: - area_1, area_2 = link_or_cluster.split("%") - if area_1 not in study_data.config.areas or area_2 not in study_data.config.areas[area_1].links: - return CommandOutput( - status=False, - message=f"Link '{link_or_cluster}' does not exist in binding constraint '{bd_id}'", - ) - elif "." in link_or_cluster: - # Cluster IDs are stored in lower case in the binding constraints file. - area, cluster_id = link_or_cluster.split(".") - thermal_ids = {thermal.id.lower() for thermal in study_data.config.areas[area].thermals} - if area not in study_data.config.areas or cluster_id.lower() not in thermal_ids: - return CommandOutput( - status=False, - message=f"Cluster '{link_or_cluster}' does not exist in binding constraint '{bd_id}'", - ) - else: - raise NotImplementedError(f"Invalid link or thermal ID: {link_or_cluster}") - - # this is weird because Antares Simulator only accept int as offset - if len(coeffs[link_or_cluster]) == 2: - coeffs[link_or_cluster][1] = int(coeffs[link_or_cluster][1]) - - binding_constraints[new_key][link_or_cluster] = "%".join( - [str(coeff_val) for coeff_val in coeffs[link_or_cluster]] - ) - parse_bindings_coeffs_and_save_into_config(bd_id, study_data.config, coeffs) - study_data.tree.save( - binding_constraints, - ["input", "bindingconstraints", "bindingconstraints"], - ) - if values: - if not isinstance(values, str): # pragma: no cover - raise TypeError(repr(values)) - study_data.tree.save(values, ["input", "bindingconstraints", bd_id]) - return CommandOutput(status=True) +from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import BindingConstraintFrequency +from antarest.study.storage.rawstudy.model.filesystem.config.model import BindingConstraintDTO, FileStudyTreeConfig def parse_bindings_coeffs_and_save_into_config( bd_id: str, study_data_config: FileStudyTreeConfig, - coeffs: Mapping[str, Union[Literal["hourly", "daily", "weekly"], Sequence[float]]], + coeffs: t.Mapping[str, t.Union[t.Literal["hourly", "daily", "weekly"], t.Sequence[float]]], ) -> None: if bd_id not in [bind.id for bind in study_data_config.bindings]: areas_set = set() diff --git a/antarest/study/storage/variantstudy/command_factory.py b/antarest/study/storage/variantstudy/command_factory.py index 5fe5c7d9cb..c4803ce0cc 100644 --- a/antarest/study/storage/variantstudy/command_factory.py +++ b/antarest/study/storage/variantstudy/command_factory.py @@ -1,4 +1,4 @@ -from typing import List +import typing as t from antarest.core.model import JSON from antarest.matrixstore.service import ISimpleMatrixService @@ -74,17 +74,19 @@ def __init__( patch_service=patch_service, ) - def _to_single_command(self, action: str, args: JSON) -> ICommand: + def _to_single_command(self, action: str, args: JSON, version: int, command_id: t.Optional[str]) -> ICommand: """Convert a single CommandDTO to ICommand.""" if action in COMMAND_MAPPING: command_class = COMMAND_MAPPING[action] - return command_class( + return command_class( # type: ignore **args, command_context=self.command_context, - ) # type: ignore + version=version, + command_id=command_id, + ) raise NotImplementedError(action) - def to_command(self, command_dto: CommandDTO) -> List[ICommand]: + def to_command(self, command_dto: CommandDTO) -> t.List[ICommand]: """ Convert a CommandDTO to a list of ICommand. @@ -99,12 +101,15 @@ def to_command(self, command_dto: CommandDTO) -> List[ICommand]: """ args = command_dto.args if isinstance(args, dict): - return [self._to_single_command(command_dto.action, args)] + return [self._to_single_command(command_dto.action, args, command_dto.version, command_dto.id)] elif isinstance(args, list): - return [self._to_single_command(command_dto.action, argument) for argument in args] + return [ + self._to_single_command(command_dto.action, argument, command_dto.version, command_dto.id) + for argument in args + ] raise NotImplementedError() - def to_commands(self, cmd_dto_list: List[CommandDTO]) -> List[ICommand]: + def to_commands(self, cmd_dto_list: t.List[CommandDTO]) -> t.List[ICommand]: """ Convert a list of CommandDTO to a list of ICommand. diff --git a/antarest/study/storage/variantstudy/model/command/common.py b/antarest/study/storage/variantstudy/model/command/common.py index a6ac905fd9..40ec8629cf 100644 --- a/antarest/study/storage/variantstudy/model/command/common.py +++ b/antarest/study/storage/variantstudy/model/command/common.py @@ -8,13 +8,6 @@ class CommandOutput: message: str = "" -class BindingConstraintOperator(Enum): - BOTH = "both" - EQUAL = "equal" - GREATER = "greater" - LESS = "less" - - class CoeffType(Enum): THERMAL = "thermal" LINK = "link" diff --git a/antarest/study/storage/variantstudy/model/command/create_area.py b/antarest/study/storage/variantstudy/model/command/create_area.py index d2114c254e..f956ef298c 100644 --- a/antarest/study/storage/variantstudy/model/command/create_area.py +++ b/antarest/study/storage/variantstudy/model/command/create_area.py @@ -5,8 +5,8 @@ from antarest.core.model import JSON from antarest.study.common.default_values import FilteringOptions, NodalOptimization from antarest.study.storage.rawstudy.model.filesystem.config.model import ( - ENR_MODELLING, Area, + EnrModelling, FileStudyTreeConfig, transform_name_to_id, ) @@ -238,7 +238,7 @@ def _apply(self, study_data: FileStudy) -> CommandOutput: f"waterValues_{area_id}" ] = self.command_context.generator_matrix_constants.get_null_matrix() - if version >= 810 and study_data.config.enr_modelling == ENR_MODELLING.CLUSTERS.value: + if version >= 810 and study_data.config.enr_modelling == EnrModelling.CLUSTERS.value: new_area_data["input"]["renewables"] = { "clusters": {area_id: {"list": {}}}, } diff --git a/antarest/study/storage/variantstudy/model/command/create_binding_constraint.py b/antarest/study/storage/variantstudy/model/command/create_binding_constraint.py index 79783e1bc9..96e9643165 100644 --- a/antarest/study/storage/variantstudy/model/command/create_binding_constraint.py +++ b/antarest/study/storage/variantstudy/model/command/create_binding_constraint.py @@ -1,174 +1,385 @@ +import json +import typing as t from abc import ABCMeta -from typing import Any, Dict, List, Optional, Tuple, Union, cast import numpy as np -from pydantic import BaseModel, Field, validator +from pydantic import BaseModel, Extra, Field, root_validator, validator from antarest.matrixstore.model import MatrixData -from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import BindingConstraintFrequency +from antarest.study.business.all_optional_meta import AllOptionalMetaclass +from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import ( + BindingConstraintFrequency, + BindingConstraintOperator, +) +from antarest.study.storage.rawstudy.model.filesystem.config.field_validators import validate_filtering from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig, transform_name_to_id from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy from antarest.study.storage.variantstudy.business.matrix_constants_generator import GeneratorMatrixConstants -from antarest.study.storage.variantstudy.business.utils import strip_matrix_protocol, validate_matrix +from antarest.study.storage.variantstudy.business.utils import validate_matrix from antarest.study.storage.variantstudy.business.utils_binding_constraint import ( - apply_binding_constraint, parse_bindings_coeffs_and_save_into_config, ) -from antarest.study.storage.variantstudy.model.command.common import ( - BindingConstraintOperator, - CommandName, - CommandOutput, -) +from antarest.study.storage.variantstudy.model.command.common import CommandName, CommandOutput from antarest.study.storage.variantstudy.model.command.icommand import MATCH_SIGNATURE_SEPARATOR, ICommand from antarest.study.storage.variantstudy.model.model import CommandDTO -__all__ = ( - "AbstractBindingConstraintCommand", - "CreateBindingConstraint", - "check_matrix_values", - "BindingConstraintProperties", -) +TERM_MATRICES = ["less_term_matrix", "equal_term_matrix", "greater_term_matrix"] +DEFAULT_GROUP = "default" + +MatrixType = t.List[t.List[MatrixData]] -MatrixType = List[List[MatrixData]] +EXPECTED_MATRIX_SHAPES = { + BindingConstraintFrequency.HOURLY: (8784, 3), + BindingConstraintFrequency.DAILY: (366, 3), + BindingConstraintFrequency.WEEKLY: (366, 3), +} -def check_matrix_values(time_step: BindingConstraintFrequency, values: MatrixType) -> None: +def check_matrix_values(time_step: BindingConstraintFrequency, values: MatrixType, version: int) -> None: """ Check the binding constraint's matrix values for the specified time step. Args: time_step: The frequency of the binding constraint: "hourly", "daily" or "weekly". values: The binding constraint's 2nd member matrix. + version: Study version. Raises: ValueError: If the matrix shape does not match the expected shape for the given time step. If the matrix values contain NaN (Not-a-Number). """ - # Matrice shapes for binding constraints are different from usual shapes, + # Matrix shapes for binding constraints are different from usual shapes, # because we need to take leap years into account, which contains 366 days and 8784 hours. # Also, we use the same matrices for "weekly" and "daily" frequencies, # because the solver calculates the weekly matrix from the daily matrix. # See https://github.com/AntaresSimulatorTeam/AntaREST/issues/1843 - shapes = { - BindingConstraintFrequency.HOURLY: (8784, 3), - BindingConstraintFrequency.DAILY: (366, 3), - BindingConstraintFrequency.WEEKLY: (366, 3), - } # Check the matrix values and create the corresponding matrix link array = np.array(values, dtype=np.float64) - if array.shape != shapes[time_step]: - raise ValueError(f"Invalid matrix shape {array.shape}, expected {shapes[time_step]}") + expected_shape = EXPECTED_MATRIX_SHAPES[time_step] + actual_shape = array.shape + if version < 870: + if actual_shape != expected_shape: + raise ValueError(f"Invalid matrix shape {actual_shape}, expected {expected_shape}") + elif actual_shape[0] != expected_shape[0]: + raise ValueError(f"Invalid matrix length {actual_shape[0]}, expected {expected_shape[0]}") if np.isnan(array).any(): raise ValueError("Matrix values cannot contain NaN") -class BindingConstraintProperties(BaseModel): - # todo: add the `name` attribute because it should also be updated - # It would lead to an API change as update_binding_constraint currently does not have it +# ================================================================================= +# Binding constraint properties classes +# ================================================================================= + + +class BindingConstraintPropertiesBase(BaseModel, extra=Extra.forbid, allow_population_by_field_name=True): enabled: bool = True - time_step: BindingConstraintFrequency - operator: BindingConstraintOperator - coeffs: Dict[str, List[float]] - values: Optional[Union[MatrixType, str]] = Field(None, description="2nd member matrix") - filter_year_by_year: Optional[str] = None - filter_synthesis: Optional[str] = None - comments: Optional[str] = None + time_step: BindingConstraintFrequency = Field(BindingConstraintFrequency.HOURLY, alias="type") + operator: BindingConstraintOperator = BindingConstraintOperator.EQUAL + comments: str = "" + + @classmethod + def from_dict(cls, **attrs: t.Any) -> "BindingConstraintPropertiesBase": + """ + Instantiate a class from a dictionary excluding unknown or `None` fields. + """ + attrs = {k: v for k, v in attrs.items() if k in cls.__fields__ and v is not None} + return cls(**attrs) + + +class BindingConstraintProperties830(BindingConstraintPropertiesBase): + filter_year_by_year: str = Field("", alias="filter-year-by-year") + filter_synthesis: str = Field("", alias="filter-synthesis") + + @validator("filter_synthesis", "filter_year_by_year", pre=True) + def _validate_filtering(cls, v: t.Any) -> str: + return validate_filtering(v) -class AbstractBindingConstraintCommand(BindingConstraintProperties, ICommand, metaclass=ABCMeta): +class BindingConstraintProperties870(BindingConstraintProperties830): + group: str = DEFAULT_GROUP + + +BindingConstraintProperties = t.Union[ + BindingConstraintPropertiesBase, + BindingConstraintProperties830, + BindingConstraintProperties870, +] + + +def get_binding_constraint_config_cls(study_version: t.Union[str, int]) -> t.Type[BindingConstraintProperties]: """ - Abstract class for binding constraint commands. + Retrieves the binding constraint configuration class based on the study version. """ + version = int(study_version) + if version >= 870: + return BindingConstraintProperties870 + elif version >= 830: + return BindingConstraintProperties830 + else: + return BindingConstraintPropertiesBase - def to_dto(self) -> CommandDTO: - args = { - "enabled": self.enabled, - "time_step": self.time_step.value, - "operator": self.operator.value, - "coeffs": self.coeffs, - "comments": self.comments, - "filter_year_by_year": self.filter_year_by_year, - "filter_synthesis": self.filter_synthesis, - } - if self.values is not None: - args["values"] = strip_matrix_protocol(self.values) - return CommandDTO( - action=self.command_name.value, - args=args, - ) - def get_inner_matrices(self) -> List[str]: - if self.values is not None: - if not isinstance(self.values, str): # pragma: no cover - raise TypeError(repr(self.values)) - return [strip_matrix_protocol(self.values)] - return [] +def create_binding_constraint_config(study_version: t.Union[str, int], **kwargs: t.Any) -> BindingConstraintProperties: + """ + Factory method to create a binding constraint configuration model. + Args: + study_version: The version of the study. + **kwargs: The properties to be used to initialize the model. -class CreateBindingConstraint(AbstractBindingConstraintCommand): + Returns: + The binding_constraint configuration model. """ - Command used to create a binding constraint. + cls = get_binding_constraint_config_cls(study_version) + return cls.from_dict(**kwargs) + + +class OptionalProperties(BindingConstraintProperties870, metaclass=AllOptionalMetaclass, use_none=True): + pass + + +# ================================================================================= +# Binding constraint matrices classes +# ================================================================================= + + +class BindingConstraintMatrices(BaseModel, extra=Extra.forbid, allow_population_by_field_name=True): + """ + Class used to store the matrices of a binding constraint. """ - command_name = CommandName.CREATE_BINDING_CONSTRAINT - version: int = 1 + values: t.Optional[t.Union[MatrixType, str]] = Field( + None, + description="2nd member matrix for studies before v8.7", + ) + less_term_matrix: t.Optional[t.Union[MatrixType, str]] = Field( + None, + description="less term matrix for v8.7+ studies", + alias="lessTermMatrix", + ) + greater_term_matrix: t.Optional[t.Union[MatrixType, str]] = Field( + None, + description="greater term matrix for v8.7+ studies", + alias="greaterTermMatrix", + ) + equal_term_matrix: t.Optional[t.Union[MatrixType, str]] = Field( + None, + description="equal term matrix for v8.7+ studies", + alias="equalTermMatrix", + ) - # Properties of the `CREATE_BINDING_CONSTRAINT` command: - name: str + @root_validator(pre=True) + def check_matrices( + cls, values: t.Dict[str, t.Optional[t.Union[MatrixType, str]]] + ) -> t.Dict[str, t.Optional[t.Union[MatrixType, str]]]: + values_matrix = values.get("values") or None + less_term_matrix = values.get("less_term_matrix") or None + greater_term_matrix = values.get("greater_term_matrix") or None + equal_term_matrix = values.get("equal_term_matrix") or None + if values_matrix and (less_term_matrix or greater_term_matrix or equal_term_matrix): + raise ValueError( + "You cannot fill 'values' (matrix before v8.7) and a matrix term:" + " 'less_term_matrix', 'greater_term_matrix' or 'equal_term_matrix' (matrices since v8.7)" + ) + + return values + + +# ================================================================================= +# Binding constraint command classes +# ================================================================================= + + +class AbstractBindingConstraintCommand(OptionalProperties, BindingConstraintMatrices, ICommand, metaclass=ABCMeta): + """ + Abstract class for binding constraint commands. + """ + + coeffs: t.Optional[t.Dict[str, t.List[float]]] + + def to_dto(self) -> CommandDTO: + json_command = json.loads(self.json(exclude={"command_context"})) + args = {} + for field in ["enabled", "coeffs", "comments", "time_step", "operator"]: + if json_command[field]: + args[field] = json_command[field] + + # The `filter_year_by_year` and `filter_synthesis` attributes are only available for studies since v8.3 + if self.filter_synthesis: + args["filter_synthesis"] = self.filter_synthesis + if self.filter_year_by_year: + args["filter_year_by_year"] = self.filter_year_by_year + + # The `group` attribute is only available for studies since v8.7 + if self.group: + args["group"] = self.group + + matrix_service = self.command_context.matrix_service + for matrix_name in TERM_MATRICES + ["values"]: + matrix_attr = getattr(self, matrix_name, None) + if matrix_attr is not None: + args[matrix_name] = matrix_service.get_matrix_id(matrix_attr) + + return CommandDTO(action=self.command_name.value, args=args, version=self.version) + + def get_inner_matrices(self) -> t.List[str]: + matrix_service = self.command_context.matrix_service + return [ + matrix_service.get_matrix_id(matrix) + for matrix in [ + self.values, + self.less_term_matrix, + self.greater_term_matrix, + self.equal_term_matrix, + ] + if matrix is not None + ] + + def get_corresponding_matrices( + self, v: t.Optional[t.Union[MatrixType, str]], time_step: BindingConstraintFrequency, version: int, create: bool + ) -> t.Optional[str]: + constants: GeneratorMatrixConstants = self.command_context.generator_matrix_constants - @validator("values", always=True) - def validate_series( - cls, - v: Optional[Union[MatrixType, str]], - values: Dict[str, Any], - ) -> Optional[Union[MatrixType, str]]: - constants: GeneratorMatrixConstants - constants = values["command_context"].generator_matrix_constants - time_step = values["time_step"] if v is None: - # Use an already-registered default matrix + if not create: + # The matrix is not updated + return None + # Use already-registered default matrix methods = { - BindingConstraintFrequency.HOURLY: constants.get_binding_constraint_hourly, - BindingConstraintFrequency.DAILY: constants.get_binding_constraint_daily, - BindingConstraintFrequency.WEEKLY: constants.get_binding_constraint_weekly, + "before_v87": { + BindingConstraintFrequency.HOURLY: constants.get_binding_constraint_hourly_86, + BindingConstraintFrequency.DAILY: constants.get_binding_constraint_daily_weekly_86, + BindingConstraintFrequency.WEEKLY: constants.get_binding_constraint_daily_weekly_86, + }, + "after_v87": { + BindingConstraintFrequency.HOURLY: constants.get_binding_constraint_hourly_87, + BindingConstraintFrequency.DAILY: constants.get_binding_constraint_daily_weekly_87, + BindingConstraintFrequency.WEEKLY: constants.get_binding_constraint_daily_weekly_87, + }, } - method = methods[time_step] - return method() + return methods["before_v87"][time_step]() if version < 870 else methods["after_v87"][time_step]() if isinstance(v, str): # Check the matrix link - return validate_matrix(v, values) + return validate_matrix(v, {"command_context": self.command_context}) if isinstance(v, list): - check_matrix_values(time_step, v) - return validate_matrix(v, values) + check_matrix_values(time_step, v, version) + return validate_matrix(v, {"command_context": self.command_context}) # Invalid datatype # pragma: no cover raise TypeError(repr(v)) - def _apply_config(self, study_data_config: FileStudyTreeConfig) -> Tuple[CommandOutput, Dict[str, Any]]: + def validates_and_fills_matrices( + self, + *, + time_step: BindingConstraintFrequency, + specific_matrices: t.Optional[t.List[str]], + version: int, + create: bool, + ) -> None: + if version < 870: + self.values = self.get_corresponding_matrices(self.values, time_step, version, create) + elif specific_matrices: + for matrix in specific_matrices: + setattr( + self, matrix, self.get_corresponding_matrices(getattr(self, matrix), time_step, version, create) + ) + else: + self.less_term_matrix = self.get_corresponding_matrices(self.less_term_matrix, time_step, version, create) + self.greater_term_matrix = self.get_corresponding_matrices( + self.greater_term_matrix, time_step, version, create + ) + self.equal_term_matrix = self.get_corresponding_matrices(self.equal_term_matrix, time_step, version, create) + + def apply_binding_constraint( + self, study_data: FileStudy, binding_constraints: t.Dict[str, t.Any], new_key: str, bd_id: str + ) -> CommandOutput: + version = study_data.config.version + + if self.coeffs: + for link_or_cluster in self.coeffs: + if "%" in link_or_cluster: + area_1, area_2 = link_or_cluster.split("%") + if area_1 not in study_data.config.areas or area_2 not in study_data.config.areas[area_1].links: + return CommandOutput( + status=False, + message=f"Link '{link_or_cluster}' does not exist in binding constraint '{bd_id}'", + ) + elif "." in link_or_cluster: + # Cluster IDs are stored in lower case in the binding constraints file. + area, cluster_id = link_or_cluster.split(".") + thermal_ids = {thermal.id.lower() for thermal in study_data.config.areas[area].thermals} + if area not in study_data.config.areas or cluster_id.lower() not in thermal_ids: + return CommandOutput( + status=False, + message=f"Cluster '{link_or_cluster}' does not exist in binding constraint '{bd_id}'", + ) + else: + raise NotImplementedError(f"Invalid link or thermal ID: {link_or_cluster}") + + # this is weird because Antares Simulator only accept int as offset + if len(self.coeffs[link_or_cluster]) == 2: + self.coeffs[link_or_cluster][1] = int(self.coeffs[link_or_cluster][1]) + + binding_constraints[new_key][link_or_cluster] = "%".join( + [str(coeff_val) for coeff_val in self.coeffs[link_or_cluster]] + ) + parse_bindings_coeffs_and_save_into_config(bd_id, study_data.config, self.coeffs or {}) + study_data.tree.save( + binding_constraints, + ["input", "bindingconstraints", "bindingconstraints"], + ) + if self.values: + if not isinstance(self.values, str): # pragma: no cover + raise TypeError(repr(self.values)) + if version < 870: + study_data.tree.save(self.values, ["input", "bindingconstraints", bd_id]) + for matrix_term, matrix_name, matrix_alias in zip( + [self.less_term_matrix, self.equal_term_matrix, self.greater_term_matrix], + TERM_MATRICES, + ["lt", "eq", "gt"], + ): + if matrix_term: + if not isinstance(matrix_term, str): # pragma: no cover + raise TypeError(repr(matrix_term)) + if version >= 870: + study_data.tree.save(matrix_term, ["input", "bindingconstraints", f"{bd_id}_{matrix_alias}"]) + return CommandOutput(status=True) + + +class CreateBindingConstraint(AbstractBindingConstraintCommand): + """ + Command used to create a binding constraint. + """ + + command_name = CommandName.CREATE_BINDING_CONSTRAINT + version: int = 1 + + # Properties of the `CREATE_BINDING_CONSTRAINT` command: + name: str + + def _apply_config(self, study_data_config: FileStudyTreeConfig) -> t.Tuple[CommandOutput, t.Dict[str, t.Any]]: bd_id = transform_name_to_id(self.name) - parse_bindings_coeffs_and_save_into_config(bd_id, study_data_config, self.coeffs) + parse_bindings_coeffs_and_save_into_config(bd_id, study_data_config, self.coeffs or {}) return CommandOutput(status=True), {} def _apply(self, study_data: FileStudy) -> CommandOutput: binding_constraints = study_data.tree.get(["input", "bindingconstraints", "bindingconstraints"]) - new_key = len(binding_constraints) + new_key = str(len(binding_constraints)) bd_id = transform_name_to_id(self.name) - return apply_binding_constraint( - study_data, - binding_constraints, - str(new_key), - bd_id, - self.name, - self.comments, - self.enabled, - self.time_step, - self.operator, - self.coeffs, - self.values, - self.filter_year_by_year, - self.filter_synthesis, + + study_version = study_data.config.version + props = create_binding_constraint_config(study_version, **self.dict()) + obj = json.loads(props.json(by_alias=True)) + + new_binding = {"id": bd_id, "name": self.name, **obj} + + binding_constraints[new_key] = new_binding + + self.validates_and_fills_matrices( + time_step=props.time_step, specific_matrices=None, version=study_version, create=True ) + return super().apply_binding_constraint(study_data, binding_constraints, new_key, bd_id) def to_dto(self) -> CommandDTO: dto = super().to_dto() @@ -178,38 +389,44 @@ def to_dto(self) -> CommandDTO: def match_signature(self) -> str: return str(self.command_name.value + MATCH_SIGNATURE_SEPARATOR + self.name) - def match(self, other: ICommand, equal: bool = False) -> bool: - if not isinstance(other, CreateBindingConstraint): - return False - simple_match = self.name == other.name - if not equal: - return simple_match - return ( - simple_match - and self.enabled == other.enabled - and self.time_step == other.time_step - and self.operator == other.operator - and self.coeffs == other.coeffs - and self.values == other.values - and self.comments == other.comments - ) - - def _create_diff(self, other: "ICommand") -> List["ICommand"]: - other = cast(CreateBindingConstraint, other) + def _create_diff(self, other: "ICommand") -> t.List["ICommand"]: from antarest.study.storage.variantstudy.model.command.update_binding_constraint import UpdateBindingConstraint + other = t.cast(CreateBindingConstraint, other) bd_id = transform_name_to_id(self.name) - return [ - UpdateBindingConstraint( - id=bd_id, - enabled=other.enabled, - time_step=other.time_step, - operator=other.operator, - coeffs=other.coeffs, - values=strip_matrix_protocol(other.values) if self.values != other.values else None, - filter_year_by_year=other.filter_year_by_year, - filter_synthesis=other.filter_synthesis, - comments=other.comments, - command_context=other.command_context, - ) + args = {"id": bd_id, "command_context": other.command_context} + + excluded_fields = frozenset(ICommand.__fields__) + self_command = json.loads(self.json(exclude=excluded_fields)) + other_command = json.loads(other.json(exclude=excluded_fields)) + properties = [ + "enabled", + "coeffs", + "comments", + "filter_year_by_year", + "filter_synthesis", + "group", + "time_step", + "operator", ] + for prop in properties: + if self_command[prop] != other_command[prop]: + args[prop] = other_command[prop] + + matrix_service = self.command_context.matrix_service + for matrix_name in ["values"] + TERM_MATRICES: + self_matrix = getattr(self, matrix_name) # matrix, ID or `None` + other_matrix = getattr(other, matrix_name) # matrix, ID or `None` + self_matrix_id = None if self_matrix is None else matrix_service.get_matrix_id(self_matrix) + other_matrix_id = None if other_matrix is None else matrix_service.get_matrix_id(other_matrix) + if self_matrix_id != other_matrix_id: + args[matrix_name] = other_matrix_id + + return [UpdateBindingConstraint(**args)] + + def match(self, other: "ICommand", equal: bool = False) -> bool: + if not isinstance(other, self.__class__): + return False + if not equal: + return self.name == other.name + return super().match(other, equal) diff --git a/antarest/study/storage/variantstudy/model/command/create_cluster.py b/antarest/study/storage/variantstudy/model/command/create_cluster.py index f9edfba949..a884eb7b9c 100644 --- a/antarest/study/storage/variantstudy/model/command/create_cluster.py +++ b/antarest/study/storage/variantstudy/model/command/create_cluster.py @@ -115,6 +115,7 @@ def _apply(self, study_data: FileStudy) -> CommandOutput: # Series identifiers are in lower case. series_id = cluster_id.lower() + null_matrix = self.command_context.generator_matrix_constants.get_null_matrix() new_cluster_data: JSON = { "input": { "thermal": { @@ -127,14 +128,13 @@ def _apply(self, study_data: FileStudy) -> CommandOutput: } } }, - "series": { - self.area_id: { - series_id: {"series": self.command_context.generator_matrix_constants.get_null_matrix()} - } - }, + "series": {self.area_id: {series_id: {"series": null_matrix}}}, } } } + if study_data.config.version >= 870: + new_cluster_data["input"]["thermal"]["series"][self.area_id][series_id]["CO2Cost"] = null_matrix + new_cluster_data["input"]["thermal"]["series"][self.area_id][series_id]["fuelCost"] = null_matrix study_data.tree.save(new_cluster_data) return output diff --git a/antarest/study/storage/variantstudy/model/command/create_renewables_cluster.py b/antarest/study/storage/variantstudy/model/command/create_renewables_cluster.py index ab61d8f710..3e5ad8e213 100644 --- a/antarest/study/storage/variantstudy/model/command/create_renewables_cluster.py +++ b/antarest/study/storage/variantstudy/model/command/create_renewables_cluster.py @@ -4,8 +4,8 @@ from antarest.core.model import JSON from antarest.study.storage.rawstudy.model.filesystem.config.model import ( - ENR_MODELLING, Area, + EnrModelling, FileStudyTreeConfig, transform_name_to_id, ) @@ -42,7 +42,7 @@ def validate_cluster_name(cls, val: str) -> str: return val def _apply_config(self, study_data: FileStudyTreeConfig) -> t.Tuple[CommandOutput, t.Dict[str, t.Any]]: - if study_data.enr_modelling != ENR_MODELLING.CLUSTERS.value: + if study_data.enr_modelling != EnrModelling.CLUSTERS.value: # Since version 8.1 of the solver, we can use renewable clusters # instead of "Load", "Wind" and "Solar" objects for modelling. # When the "renewable-generation-modelling" parameter is set to "aggregated", @@ -50,7 +50,7 @@ def _apply_config(self, study_data: FileStudyTreeConfig) -> t.Tuple[CommandOutpu # To use renewable clusters, the parameter must therefore be set to "clusters". message = ( f"Parameter 'renewable-generation-modelling'" - f" must be set to '{ENR_MODELLING.CLUSTERS.value}'" + f" must be set to '{EnrModelling.CLUSTERS.value}'" f" instead of '{study_data.enr_modelling}'" ) return CommandOutput(status=False, message=message), {} diff --git a/antarest/study/storage/variantstudy/model/command/icommand.py b/antarest/study/storage/variantstudy/model/command/icommand.py index 6a17c34c10..1c5c704320 100644 --- a/antarest/study/storage/variantstudy/model/command/icommand.py +++ b/antarest/study/storage/variantstudy/model/command/icommand.py @@ -1,6 +1,7 @@ import logging +import typing as t +import uuid from abc import ABC, abstractmethod -from typing import TYPE_CHECKING, Any, Dict, List, Tuple from pydantic import BaseModel, Extra @@ -11,20 +12,31 @@ from antarest.study.storage.variantstudy.model.command_context import CommandContext from antarest.study.storage.variantstudy.model.model import CommandDTO -if TYPE_CHECKING: # False at runtime, for mypy +if t.TYPE_CHECKING: # False at runtime, for mypy from antarest.study.storage.variantstudy.business.command_extractor import CommandExtractor MATCH_SIGNATURE_SEPARATOR = "%" logger = logging.getLogger(__name__) -class ICommand(ABC, BaseModel, extra=Extra.forbid, arbitrary_types_allowed=True): +class ICommand(ABC, BaseModel, extra=Extra.forbid, arbitrary_types_allowed=True, copy_on_model_validation="deep"): + """ + Interface for all commands that can be applied to a study. + + Attributes: + command_id: The ID of the command extracted from the database, if any. + command_name: The name of the command. + version: The version of the command (currently always equal to 1). + command_context: The context of the command. + """ + + command_id: t.Optional[uuid.UUID] = None command_name: CommandName version: int command_context: CommandContext @abstractmethod - def _apply_config(self, study_data: FileStudyTreeConfig) -> Tuple[CommandOutput, Dict[str, Any]]: + def _apply_config(self, study_data: FileStudyTreeConfig) -> t.Tuple[CommandOutput, t.Dict[str, t.Any]]: """ Applies configuration changes to the study data. @@ -98,7 +110,6 @@ def match_signature(self) -> str: """Returns the command signature.""" raise NotImplementedError() - @abstractmethod def match(self, other: "ICommand", equal: bool = False) -> bool: """ Indicate if the other command is the same type and targets the same element. @@ -109,10 +120,15 @@ def match(self, other: "ICommand", equal: bool = False) -> bool: Returns: True if the command match with the other else False """ - raise NotImplementedError() + if not isinstance(other, self.__class__): + return False + excluded_fields = set(ICommand.__fields__) + this_values = self.dict(exclude=excluded_fields) + that_values = other.dict(exclude=excluded_fields) + return this_values == that_values @abstractmethod - def _create_diff(self, other: "ICommand") -> List["ICommand"]: + def _create_diff(self, other: "ICommand") -> t.List["ICommand"]: """ Creates a list of commands representing the differences between the current instance and another `ICommand` object. @@ -126,7 +142,7 @@ def _create_diff(self, other: "ICommand") -> List["ICommand"]: """ raise NotImplementedError() - def create_diff(self, other: "ICommand") -> List["ICommand"]: + def create_diff(self, other: "ICommand") -> t.List["ICommand"]: """ Creates a list of commands representing the differences between the current instance and another `ICommand` object. @@ -142,7 +158,7 @@ def create_diff(self, other: "ICommand") -> List["ICommand"]: return self._create_diff(other) @abstractmethod - def get_inner_matrices(self) -> List[str]: + def get_inner_matrices(self) -> t.List[str]: """ Retrieves the list of matrix IDs. """ diff --git a/antarest/study/storage/variantstudy/model/command/remove_area.py b/antarest/study/storage/variantstudy/model/command/remove_area.py index a7914c627e..8703137a5a 100644 --- a/antarest/study/storage/variantstudy/model/command/remove_area.py +++ b/antarest/study/storage/variantstudy/model/command/remove_area.py @@ -38,11 +38,11 @@ def _remove_area_from_links_in_config(self, study_data_config: FileStudyTreeConf del study_data_config.areas[area_name].links[link] def _remove_area_from_sets_in_config(self, study_data_config: FileStudyTreeConfig) -> None: - for id, set in study_data_config.sets.items(): - if set.areas and self.id in set.areas: + for id_, set_ in study_data_config.sets.items(): + if set_.areas and self.id in set_.areas: with contextlib.suppress(ValueError): - set.areas.remove(self.id) - study_data_config.sets[id] = set + set_.areas.remove(self.id) + study_data_config.sets[id_] = set_ def _apply_config(self, study_data_config: FileStudyTreeConfig) -> Tuple[CommandOutput, Dict[str, Any]]: del study_data_config.areas[self.id] @@ -78,15 +78,53 @@ def _remove_area_from_links(self, study_data: FileStudy) -> None: ) def _remove_area_from_binding_constraints(self, study_data: FileStudy) -> None: - binding_constraints = study_data.tree.get(["input", "bindingconstraints", "bindingconstraints"]) + """ + Remove the binding constraints that are related to the area. - id_to_remove = {bc_id for bc_id, bc in binding_constraints.items() for key in bc if self.id in key} + Notes: + A binding constraint has properties, a list of terms (which form a linear equation) and + a right-hand side (which is the matrix of the binding constraint). + The terms are of the form `area1%area2` or `area.cluster` where `area` is the ID of the area + and `cluster` is the ID of the cluster. - for bc_id in id_to_remove: - study_data.tree.delete(["input", "bindingconstraints", binding_constraints[bc_id]["id"]]) - del binding_constraints[bc_id] + When an area is removed, it has an impact on the terms of the binding constraints. + At first, we could decide to remove the terms that are related to the area. + However, this would lead to a linear equation that is not valid anymore. - study_data.tree.save(binding_constraints, ["input", "bindingconstraints", "bindingconstraints"]) + Instead, we decide to remove the binding constraints that are related to the area. + """ + # See also `RemoveArea` + # noinspection SpellCheckingInspection + url = ["input", "bindingconstraints", "bindingconstraints"] + binding_constraints = study_data.tree.get(url) + + # Collect the binding constraints that are related to the area to remove + # by searching the terms that contain the ID of the area. + bc_to_remove = {} + lower_area_id = self.id.lower() + for bc_index, bc in list(binding_constraints.items()): + for key in bc: + # Term IDs are in the form `area1%area2` or `area.cluster` + if "%" in key: + related_areas = key.split("%") + elif "." in key: + related_areas = key.split(".")[:-1] + else: + # This key belongs to the set of properties, it isn't a term ID, so we skip it + continue + related_areas = [area.lower() for area in related_areas] + if lower_area_id in related_areas: + bc_to_remove[bc_index] = binding_constraints.pop(bc_index) + break + + matrix_suffixes = ["_lt", "_gt", "_eq"] if study_data.config.version >= 870 else [""] + + for bc_index, bc in bc_to_remove.items(): + for suffix in matrix_suffixes: + # noinspection SpellCheckingInspection + study_data.tree.delete(["input", "bindingconstraints", f"{bc['id']}{suffix}"]) + + study_data.tree.save(binding_constraints, url) def _remove_area_from_hydro_allocation(self, study_data: FileStudy) -> None: """ diff --git a/antarest/study/storage/variantstudy/model/command/remove_binding_constraint.py b/antarest/study/storage/variantstudy/model/command/remove_binding_constraint.py index 961e878443..958e9d81f1 100644 --- a/antarest/study/storage/variantstudy/model/command/remove_binding_constraint.py +++ b/antarest/study/storage/variantstudy/model/command/remove_binding_constraint.py @@ -26,11 +26,11 @@ def _apply_config(self, study_data: FileStudyTreeConfig) -> Tuple[CommandOutput, dict(), ) study_data.bindings.remove(next(iter([bind for bind in study_data.bindings if bind.id == self.id]))) - return CommandOutput(status=True), dict() + return CommandOutput(status=True), {} def _apply(self, study_data: FileStudy) -> CommandOutput: if self.id not in [bind.id for bind in study_data.config.bindings]: - return CommandOutput(status=False, message="Binding constraint not found") + return CommandOutput(status=False, message=f"Binding constraint not found: '{self.id}'") binding_constraints = study_data.tree.get(["input", "bindingconstraints", "bindingconstraints"]) new_binding_constraints: JSON = {} index = 0 @@ -43,7 +43,11 @@ def _apply(self, study_data: FileStudy) -> CommandOutput: new_binding_constraints, ["input", "bindingconstraints", "bindingconstraints"], ) - study_data.tree.delete(["input", "bindingconstraints", self.id]) + if study_data.config.version < 870: + study_data.tree.delete(["input", "bindingconstraints", self.id]) + else: + for term in ["lt", "gt", "eq"]: + study_data.tree.delete(["input", "bindingconstraints", f"{self.id}_{term}"]) output, _ = self._apply_config(study_data.config) return output diff --git a/antarest/study/storage/variantstudy/model/command/remove_cluster.py b/antarest/study/storage/variantstudy/model/command/remove_cluster.py index 095e62f526..fbefaea312 100644 --- a/antarest/study/storage/variantstudy/model/command/remove_cluster.py +++ b/antarest/study/storage/variantstudy/model/command/remove_cluster.py @@ -134,26 +134,50 @@ def _create_diff(self, other: "ICommand") -> t.List["ICommand"]: def get_inner_matrices(self) -> t.List[str]: return [] - # noinspection SpellCheckingInspection def _remove_cluster_from_binding_constraints(self, study_data: FileStudy) -> None: - config = study_data.tree.get(["input", "bindingconstraints", "bindingconstraints"]) - - # Binding constraints IDs to remove - ids_to_remove = set() - - # Cluster IDs are stored in lower case in the binding contraints configuration file. - cluster_id = self.cluster_id.lower() - for bc_id, bc_props in config.items(): - if f"{self.area_id}.{cluster_id}" in bc_props.keys(): - ids_to_remove.add(bc_id) - - for bc_id in ids_to_remove: - study_data.tree.delete(["input", "bindingconstraints", config[bc_id]["id"]]) - bc = next(iter([bind for bind in study_data.config.bindings if bind.id == config[bc_id]["id"]])) - study_data.config.bindings.remove(bc) - del config[bc_id] - - study_data.tree.save( - config, - ["input", "bindingconstraints", "bindingconstraints"], - ) + """ + Remove the binding constraints that are related to the thermal cluster. + + Notes: + A binding constraint has properties, a list of terms (which form a linear equation) and + a right-hand side (which is the matrix of the binding constraint). + The terms are of the form `area1%area2` or `area.cluster` where `area` is the ID of the area + and `cluster` is the ID of the cluster. + + When a thermal cluster is removed, it has an impact on the terms of the binding constraints. + At first, we could decide to remove the terms that are related to the area. + However, this would lead to a linear equation that is not valid anymore. + + Instead, we decide to remove the binding constraints that are related to the cluster. + """ + # See also `RemoveCluster` + # noinspection SpellCheckingInspection + url = ["input", "bindingconstraints", "bindingconstraints"] + binding_constraints = study_data.tree.get(url) + + # Collect the binding constraints that are related to the area to remove + # by searching the terms that contain the ID of the area. + bc_to_remove = {} + lower_area_id = self.area_id.lower() + lower_cluster_id = self.cluster_id.lower() + for bc_index, bc in list(binding_constraints.items()): + for key in bc: + if "." not in key: + # This key identifies a link or belongs to the set of properties. + # It isn't a cluster ID, so we skip it. + continue + # Term IDs are in the form `area1%area2` or `area.cluster` + # noinspection PyTypeChecker + related_area_id, related_cluster_id = map(str.lower, key.split(".")) + if (lower_area_id, lower_cluster_id) == (related_area_id, related_cluster_id): + bc_to_remove[bc_index] = binding_constraints.pop(bc_index) + break + + matrix_suffixes = ["_lt", "_gt", "_eq"] if study_data.config.version >= 870 else [""] + + for bc_index, bc in bc_to_remove.items(): + for suffix in matrix_suffixes: + # noinspection SpellCheckingInspection + study_data.tree.delete(["input", "bindingconstraints", f"{bc['id']}{suffix}"]) + + study_data.tree.save(binding_constraints, url) diff --git a/antarest/study/storage/variantstudy/model/command/update_binding_constraint.py b/antarest/study/storage/variantstudy/model/command/update_binding_constraint.py index ea52dca4c4..8befaccac1 100644 --- a/antarest/study/storage/variantstudy/model/command/update_binding_constraint.py +++ b/antarest/study/storage/variantstudy/model/command/update_binding_constraint.py @@ -1,23 +1,20 @@ -from typing import Any, Dict, List, Optional, Tuple, Union - -from pydantic import validator +import json +from typing import Any, Dict, List, Mapping, Optional, Tuple from antarest.core.model import JSON from antarest.matrixstore.model import MatrixData +from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import BindingConstraintFrequency from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy -from antarest.study.storage.variantstudy.business.utils import validate_matrix -from antarest.study.storage.variantstudy.business.utils_binding_constraint import apply_binding_constraint from antarest.study.storage.variantstudy.model.command.common import CommandName, CommandOutput from antarest.study.storage.variantstudy.model.command.create_binding_constraint import ( + TERM_MATRICES, AbstractBindingConstraintCommand, - check_matrix_values, + create_binding_constraint_config, ) from antarest.study.storage.variantstudy.model.command.icommand import MATCH_SIGNATURE_SEPARATOR, ICommand from antarest.study.storage.variantstudy.model.model import CommandDTO -__all__ = ("UpdateBindingConstraint",) - MatrixType = List[List[MatrixData]] @@ -38,84 +35,74 @@ class UpdateBindingConstraint(AbstractBindingConstraintCommand): # Properties of the `UPDATE_BINDING_CONSTRAINT` command: id: str - @validator("values", always=True) - def validate_series( - cls, - v: Optional[Union[MatrixType, str]], - values: Dict[str, Any], - ) -> Optional[Union[MatrixType, str]]: - time_step = values["time_step"] - if v is None: - # The matrix is not updated - return None - if isinstance(v, str): - # Check the matrix link - return validate_matrix(v, values) - if isinstance(v, list): - check_matrix_values(time_step, v) - return validate_matrix(v, values) - # Invalid datatype - # pragma: no cover - raise TypeError(repr(v)) - def _apply_config(self, study_data: FileStudyTreeConfig) -> Tuple[CommandOutput, Dict[str, Any]]: return CommandOutput(status=True), {} + def _find_binding_config(self, binding_constraints: Mapping[str, JSON]) -> Optional[Tuple[str, JSON]]: + """ + Find the binding constraint with the given ID in the list of binding constraints, + and returns its index and configuration, or `None` if it does not exist. + """ + for index, binding_config in binding_constraints.items(): + if binding_config["id"] == self.id: + # convert to string because the index could be an integer + return str(index), binding_config + return None + def _apply(self, study_data: FileStudy) -> CommandOutput: binding_constraints = study_data.tree.get(["input", "bindingconstraints", "bindingconstraints"]) - binding: Optional[JSON] = None - new_key: Optional[str] = None - for key, binding_config in binding_constraints.items(): - if binding_config["id"] == self.id: - binding = binding_config - new_key = key - break - if binding is None or new_key is None: + index_and_cfg = self._find_binding_config(binding_constraints) + if index_and_cfg is None: return CommandOutput( status=False, - message="Failed to retrieve existing binding constraint", + message="The binding constraint with ID '{self.id}' does not exist", ) - return apply_binding_constraint( - study_data, - binding_constraints, - new_key, - self.id, - binding["name"], - self.comments, - self.enabled, - self.time_step, - self.operator, - self.coeffs, - self.values, - self.filter_year_by_year, - self.filter_synthesis, + index, actual_cfg = index_and_cfg + + updated_matrices = [term for term in TERM_MATRICES if hasattr(self, term) and getattr(self, term)] + study_version = study_data.config.version + time_step = self.time_step or BindingConstraintFrequency(actual_cfg.get("type")) + self.validates_and_fills_matrices( + time_step=time_step, specific_matrices=updated_matrices or None, version=study_version, create=False ) + study_version = study_data.config.version + props = create_binding_constraint_config(study_version, **self.dict()) + obj = json.loads(props.json(by_alias=True, exclude_unset=True)) + + updated_cfg = binding_constraints[index] + updated_cfg.update(obj) + + if self.coeffs: + # Remove terms which IDs contain a "%" or a "." in their name + term_ids = {k for k in updated_cfg if "%" in k or "." in k} + binding_constraints[index] = {k: v for k, v in updated_cfg.items() if k not in term_ids} + + return super().apply_binding_constraint(study_data, binding_constraints, index, self.id) + def to_dto(self) -> CommandDTO: - dto = super().to_dto() - dto.args["id"] = self.id # type: ignore - return dto + matrices = ["values"] + TERM_MATRICES + matrix_service = self.command_context.matrix_service + + excluded_fields = frozenset(ICommand.__fields__) + json_command = json.loads(self.json(exclude=excluded_fields, exclude_none=True)) + for key in json_command: + if key in matrices: + json_command[key] = matrix_service.get_matrix_id(json_command[key]) + + return CommandDTO(action=self.command_name.value, args=json_command, version=self.version) def match_signature(self) -> str: return str(self.command_name.value + MATCH_SIGNATURE_SEPARATOR + self.id) - def match(self, other: ICommand, equal: bool = False) -> bool: - if not isinstance(other, UpdateBindingConstraint): - return False - simple_match = self.id == other.id - if not equal: - return simple_match - return ( - simple_match - and self.enabled == other.enabled - and self.time_step == other.time_step - and self.operator == other.operator - and self.coeffs == other.coeffs - and self.values == other.values - and self.comments == other.comments - ) - def _create_diff(self, other: "ICommand") -> List["ICommand"]: return [other] + + def match(self, other: "ICommand", equal: bool = False) -> bool: + if not isinstance(other, self.__class__): + return False + if not equal: + return self.id == other.id + return super().match(other, equal) diff --git a/antarest/study/storage/variantstudy/model/command/update_config.py b/antarest/study/storage/variantstudy/model/command/update_config.py index 91caa6a738..29887d42e1 100644 --- a/antarest/study/storage/variantstudy/model/command/update_config.py +++ b/antarest/study/storage/variantstudy/model/command/update_config.py @@ -27,7 +27,7 @@ class UpdateConfig(ICommand): data: Union[str, int, float, bool, JSON, None] def _apply_config(self, study_data: FileStudyTreeConfig) -> Tuple[CommandOutput, Dict[str, Any]]: - return CommandOutput(status=True, message="ok"), dict() + return CommandOutput(status=True, message="ok"), {} def _apply(self, study_data: FileStudy) -> CommandOutput: url = self.target.split("/") diff --git a/antarest/study/storage/variantstudy/model/dbmodel.py b/antarest/study/storage/variantstudy/model/dbmodel.py index 15b1bb896d..d9a7e5fc55 100644 --- a/antarest/study/storage/variantstudy/model/dbmodel.py +++ b/antarest/study/storage/variantstudy/model/dbmodel.py @@ -21,7 +21,7 @@ class VariantStudySnapshot(Base): # type: ignore id: str = Column( String(36), - ForeignKey("variantstudy.id"), + ForeignKey("variantstudy.id", ondelete="CASCADE"), primary_key=True, ) created_at: datetime.date = Column(DateTime) @@ -48,14 +48,16 @@ class CommandBlock(Base): # type: ignore default=lambda: str(uuid.uuid4()), unique=True, ) - study_id: str = Column(String(36), ForeignKey("variantstudy.id")) + study_id: str = Column(String(36), ForeignKey("variantstudy.id", ondelete="CASCADE")) index: int = Column(Integer) command: str = Column(String(255)) version: int = Column(Integer) args: str = Column(String()) def to_dto(self) -> CommandDTO: - return CommandDTO(id=self.id, action=self.command, args=json.loads(self.args)) + # Database may lack a version number, defaulting to 1 if so. + version = self.version or 1 + return CommandDTO(id=self.id, action=self.command, args=json.loads(self.args), version=version) def __str__(self) -> str: return ( @@ -77,7 +79,7 @@ class VariantStudy(Study): id: str = Column( String(36), - ForeignKey("study.id"), + ForeignKey("study.id", ondelete="CASCADE"), primary_key=True, ) generation_task: t.Optional[str] = Column(String(), nullable=True) diff --git a/antarest/study/storage/variantstudy/model/interfaces.py b/antarest/study/storage/variantstudy/model/interfaces.py index 93def93234..31b14fabd7 100644 --- a/antarest/study/storage/variantstudy/model/interfaces.py +++ b/antarest/study/storage/variantstudy/model/interfaces.py @@ -62,7 +62,7 @@ def generate_update_config( raise NotImplementedError() @abstractmethod - def generate_update_rawfile( + def generate_update_raw_file( self, study_tree: FileStudyTree, url: List[str], diff --git a/antarest/study/storage/variantstudy/model/model.py b/antarest/study/storage/variantstudy/model/model.py index cd478742b4..e170bf4383 100644 --- a/antarest/study/storage/variantstudy/model/model.py +++ b/antarest/study/storage/variantstudy/model/model.py @@ -1,10 +1,37 @@ import typing as t +import uuid +import typing_extensions as te from pydantic import BaseModel from antarest.core.model import JSON from antarest.study.model import StudyMetadataDTO +LegacyDetailsDTO = t.Tuple[str, bool, str] +""" +Legacy details DTO: triplet of name, output status and output message. +""" + + +class NewDetailsDTO(te.TypedDict): + """ + New details DTO: dictionary with keys 'id', 'name', 'status' and 'msg'. + + Attributes: + id: command identifier (UUID) if it exists. + name: command name. + status: command status (true or false). + msg: command generation message or error message (if the status is false). + """ + + id: uuid.UUID + name: str + status: bool + msg: str + + +DetailsDTO = t.Union[LegacyDetailsDTO, NewDetailsDTO] + class GenerationResultInfoDTO(BaseModel): """ @@ -12,11 +39,11 @@ class GenerationResultInfoDTO(BaseModel): Attributes: success: A boolean indicating whether the generation process was successful. - details: A list of tuples containing detailed information about the generation process. + details: Objects containing detailed information about the generation process. """ success: bool - details: t.MutableSequence[t.Tuple[str, bool, str]] + details: t.MutableSequence[DetailsDTO] class CommandDTO(BaseModel): diff --git a/antarest/study/storage/variantstudy/repository.py b/antarest/study/storage/variantstudy/repository.py index bf2c979de1..b9f0d88dac 100644 --- a/antarest/study/storage/variantstudy/repository.py +++ b/antarest/study/storage/variantstudy/repository.py @@ -1,6 +1,6 @@ import typing as t -from sqlalchemy.orm import Session, joinedload, subqueryload # type: ignore +from sqlalchemy.orm import Session, joinedload # type: ignore from antarest.core.interfaces.cache import ICache from antarest.core.utils.fastapi_sqlalchemy import db diff --git a/antarest/study/storage/variantstudy/snapshot_generator.py b/antarest/study/storage/variantstudy/snapshot_generator.py index 138089a35e..ee4532349f 100644 --- a/antarest/study/storage/variantstudy/snapshot_generator.py +++ b/antarest/study/storage/variantstudy/snapshot_generator.py @@ -175,8 +175,15 @@ def _apply_commands( if not results.success: message = f"Failed to generate variant study {variant_study.id}" if results.details: - detail: t.Tuple[str, bool, str] = results.details[-1] - message += f": {detail[2]}" + detail = results.details[-1] + if isinstance(detail, (tuple, list)): + # old format: LegacyDetailsDTO + message += f": {detail[2]}" + elif isinstance(detail, dict): + # new format since v2.17: NewDetailsDTO + message += f": {detail['msg']}" + else: # pragma: no cover + raise NotImplementedError(f"Unexpected detail type: {type(detail)}") raise VariantGenerationError(message) return results diff --git a/antarest/study/storage/variantstudy/variant_command_generator.py b/antarest/study/storage/variantstudy/variant_command_generator.py index ebe934ce15..7e56f370ec 100644 --- a/antarest/study/storage/variantstudy/variant_command_generator.py +++ b/antarest/study/storage/variantstudy/variant_command_generator.py @@ -1,5 +1,6 @@ import logging import shutil +import uuid from pathlib import Path from typing import Callable, List, Optional, Tuple, Union, cast @@ -10,13 +11,23 @@ from antarest.study.storage.variantstudy.model.command.common import CommandOutput from antarest.study.storage.variantstudy.model.command.icommand import ICommand from antarest.study.storage.variantstudy.model.dbmodel import VariantStudy -from antarest.study.storage.variantstudy.model.model import GenerationResultInfoDTO +from antarest.study.storage.variantstudy.model.model import GenerationResultInfoDTO, NewDetailsDTO logger = logging.getLogger(__name__) APPLY_CALLBACK = Callable[[ICommand, Union[FileStudyTreeConfig, FileStudy]], CommandOutput] +class CmdNotifier: + def __init__(self, study_id: str, total_count: int) -> None: + self.index = 0 + self.study_id = study_id + self.total_count = total_count + + def __call__(self, x: float) -> None: + logger.info(f"Command {self.index}/{self.total_count} [{self.study_id}] applied in {x}s") + + class VariantCommandGenerator: def __init__(self, study_factory: StudyFactory) -> None: self.study_factory = study_factory @@ -33,53 +44,50 @@ def _generate( # Apply commands results: GenerationResultInfoDTO = GenerationResultInfoDTO(success=True, details=[]) - stopwatch.reset_current() logger.info("Applying commands") - command_index = 0 - total_commands = len(commands) - study_id = metadata.id if metadata is not None else "-" - for command_batch in commands: - command_output_status = True - command_output_message = "" - command_name = command_batch[0].command_name.value if len(command_batch) > 0 else "" + study_id = "-" if metadata is None else metadata.id + + # flatten the list of commands + all_commands = [command for command_batch in commands for command in command_batch] + + # Prepare the stopwatch + cmd_notifier = CmdNotifier(study_id, len(all_commands)) + stopwatch.reset_current() + + # Store all the outputs + for index, cmd in enumerate(all_commands, 1): try: - command_index += 1 - command_output_messages: List[str] = [] - for command in command_batch: - output = applier(command, data) - command_output_messages.append(output.message) - command_output_status = command_output_status and output.status - if not command_output_status: - break - command_output_message = "\n".join(command_output_messages) + output = applier(cmd, data) except Exception as e: - command_output_status = False - command_output_message = f"Error while applying command {command_name}" - logger.error(command_output_message, exc_info=e) - break - finally: - results.details.append( - ( - command_name, - command_output_status, - command_output_message, - ) - ) - results.success = command_output_status - if notifier: - notifier( - command_index - 1, - command_output_status, - command_output_message, - ) - stopwatch.log_elapsed( - lambda x: logger.info( - f"Command {command_index}/{total_commands} [{study_id}] {command.match_signature()} applied in {x}s" - ) + # Unhandled exception + output = CommandOutput( + status=False, + message=f"Error while applying command {cmd.command_name}", ) + logger.error(output.message, exc_info=e) + + # noinspection PyTypeChecker + detail: NewDetailsDTO = { + "id": uuid.UUID(int=0) if cmd.command_id is None else cmd.command_id, + "name": cmd.command_name.value, + "status": output.status, + "msg": output.message, + } + results.details.append(detail) + + if notifier: + notifier(index - 1, output.status, output.message) - if not results.success: + cmd_notifier.index = index + stopwatch.log_elapsed(cmd_notifier) + + # stop variant generation as soon as a command fails + if not output.status: + logger.error(f"Command {cmd.command_name} failed: {output.message}") break + + results.success = all(detail["status"] for detail in results.details) # type: ignore + data_type = isinstance(data, FileStudy) stopwatch.log_elapsed( lambda x: logger.info( diff --git a/antarest/study/storage/variantstudy/variant_study_service.py b/antarest/study/storage/variantstudy/variant_study_service.py index 582e251013..d5288e8994 100644 --- a/antarest/study/storage/variantstudy/variant_study_service.py +++ b/antarest/study/storage/variantstudy/variant_study_service.py @@ -35,11 +35,13 @@ from antarest.core.tasks.service import DEFAULT_AWAIT_MAX_TIMEOUT, ITaskService, TaskUpdateNotifier, noop_notifier from antarest.core.utils.utils import assert_this, suppress_exception from antarest.matrixstore.service import MatrixService +from antarest.study.common.default_values import AreasQueryFile, LinksQueryFile from antarest.study.model import RawStudy, Study, StudyAdditionalData, StudyMetadataDTO, StudySimResultDTO from antarest.study.storage.abstract_storage_service import AbstractStorageService from antarest.study.storage.patch_service import PatchService from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig, FileStudyTreeConfigDTO from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy, StudyFactory +from antarest.study.storage.rawstudy.model.filesystem.matrix.matrix import MatrixFrequency from antarest.study.storage.rawstudy.raw_study_service import RawStudyService from antarest.study.storage.utils import assert_permission, export_study_flat, is_managed, remove_from_cache from antarest.study.storage.variantstudy.business.utils import transform_command_to_dto @@ -176,9 +178,7 @@ def append_commands( # noinspection PyArgumentList new_commands = [ CommandBlock( - command=command.action, - args=json.dumps(command.args), - index=(first_index + i), + command=command.action, args=json.dumps(command.args), index=(first_index + i), version=command.version ) for i, command in enumerate(validated_commands) ] @@ -213,11 +213,7 @@ def replace_commands( validated_commands = transform_command_to_dto(command_objs, commands) # noinspection PyArgumentList study.commands = [ - CommandBlock( - command=command.action, - args=json.dumps(command.args), - index=i, - ) + CommandBlock(command=command.action, args=json.dumps(command.args), index=i, version=command.version) for i, command in enumerate(validated_commands) ] self.invalidate_cache(study, invalidate_self_snapshot=True) @@ -498,6 +494,62 @@ def get( use_cache=use_cache, ) + def aggregate_areas_data( + self, + metadata: Study, + output_id: str, + query_file: AreasQueryFile, + frequency: MatrixFrequency, + mc_years: t.Sequence[int], + areas_ids: t.Sequence[str], + columns_names: t.Sequence[str], + ) -> t.Dict[str, t.Any]: + """ + Entry point to fetch data inside study. + Args: + metadata: study + output_id: the simulation ID + query_file: "values", "details", "details-st-storage", "details-res" + frequency: "hourly", "daily", "weekly", "monthly", "annual" + mc_years: list of Monte Carlo years to be selected, if empty, all years are selected + areas_ids: list of areas to be selected, if empty, all areas are selected + columns_names: list of columns to be selected, if empty, all columns are selected + + Returns: the aggregated data for areas in JSON (DataFrame.to_dict(orient='split')) + + """ + self._safe_generation(metadata, timeout=60) + self.repository.refresh(metadata) + return super().aggregate_areas_data( + metadata, output_id, query_file, frequency, mc_years, areas_ids, columns_names + ) + + def aggregate_links_data( + self, + metadata: Study, + output_id: str, + query_file: LinksQueryFile, + frequency: MatrixFrequency, + mc_years: t.Sequence[int], + columns_names: t.Sequence[str], + ) -> t.Dict[str, t.Any]: + """ + Entry point to fetch data inside study. + Args: + metadata: study for which we want to aggregate output links raw data + output_id: the simulation ID + query_file: "values", "details" + frequency: "hourly", "daily", "weekly", "monthly", "annual" + mc_years: list of Monte Carlo years to be selected, if empty, all years are selected + columns_names: list of columns to be selected, if empty, all columns are selected + + Returns: the aggregated data for links in JSON (DataFrame.to_dict(orient='split')) + + """ + self._safe_generation(metadata, timeout=60) + self.repository.refresh(metadata) + return super().aggregate_links_data(metadata, output_id, query_file, frequency, mc_years, columns_names) + def create_variant_study(self, uuid: str, name: str, params: RequestParameters) -> VariantStudy: """ Create a new variant study. diff --git a/antarest/study/web/raw_studies_blueprint.py b/antarest/study/web/raw_studies_blueprint.py index 41e214d1ad..2ce44c5d48 100644 --- a/antarest/study/web/raw_studies_blueprint.py +++ b/antarest/study/web/raw_studies_blueprint.py @@ -1,15 +1,18 @@ +import collections import http import io import json import logging -import pathlib import typing as t +from pathlib import Path, PurePosixPath +import pandas as pd from fastapi import APIRouter, Body, Depends, File, HTTPException from fastapi.params import Param, Query -from starlette.responses import JSONResponse, PlainTextResponse, Response, StreamingResponse +from starlette.responses import FileResponse, JSONResponse, PlainTextResponse, Response, StreamingResponse from antarest.core.config import Config +from antarest.core.filetransfer.model import FileDownloadNotFound from antarest.core.jwt import JWTUser from antarest.core.model import SUB_JSON from antarest.core.requests import RequestParameters @@ -17,10 +20,20 @@ from antarest.core.utils.utils import sanitize_uuid from antarest.core.utils.web import APITag from antarest.login.auth import Auth +from antarest.study.business.enum_ignore_case import EnumIgnoreCase +from antarest.study.common.default_values import AreasQueryFile, LinksQueryFile from antarest.study.service import StudyService +from antarest.study.storage.rawstudy.model.filesystem.matrix.matrix import MatrixFrequency + +try: + import tables # type: ignore + import xlsxwriter # type: ignore +except ImportError: + raise ImportError("The 'xlsxwriter' and 'tables' packages are required") from None logger = logging.getLogger(__name__) + # noinspection SpellCheckingInspection CONTENT_TYPES = { @@ -49,6 +62,110 @@ } +def _split_comma_separated_values(value: str, *, default: t.Sequence[str] = ()) -> t.Sequence[str]: + """Split a comma-separated list of values into an ordered set of strings.""" + values = value.split(",") if value else default + # drop whitespace around values + values = [v.strip() for v in values] + # remove duplicates and preserve order (to have a deterministic result for unit tests). + return list(collections.OrderedDict.fromkeys(values)) + + +class TableExportFormat(EnumIgnoreCase): + """Export format for tables.""" + + XLSX = "xlsx" + HDF5 = "hdf5" + TSV = "tsv" + CSV = "csv" + CSV_SEMICOLON = "csv (semicolon)" + + def __str__(self) -> str: + """Return the format as a string for display.""" + return self.value.title() + + @property + def media_type(self) -> str: + """Return the media type used for the HTTP response.""" + if self == TableExportFormat.XLSX: + # noinspection SpellCheckingInspection + return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + elif self == TableExportFormat.TSV: + return "text/tab-separated-values" + elif self in (TableExportFormat.CSV, TableExportFormat.CSV_SEMICOLON): + return "text/csv" + elif self == TableExportFormat.HDF5: + return "application/x-hdf5" + else: # pragma: no cover + raise NotImplementedError(f"Export format '{self}' is not implemented") + + @property + def suffix(self) -> str: + """Return the file suffix for the format.""" + if self == TableExportFormat.XLSX: + return ".xlsx" + elif self == TableExportFormat.TSV: + return ".tsv" + elif self in (TableExportFormat.CSV, TableExportFormat.CSV_SEMICOLON): + return ".csv" + elif self == TableExportFormat.HDF5: + return ".h5" + else: # pragma: no cover + raise NotImplementedError(f"Export format '{self}' is not implemented") + + def export_table( + self, + df: pd.DataFrame, + export_path: t.Union[str, Path], + *, + with_index: bool = True, + with_header: bool = True, + ) -> None: + """Export a table to a file in the given format.""" + if self == TableExportFormat.XLSX: + return df.to_excel( + export_path, + index=with_index, + header=with_header, + engine="xlsxwriter", + ) + elif self == TableExportFormat.TSV: + return df.to_csv( + export_path, + sep="\t", + index=with_index, + header=with_header, + float_format="%.6f", + ) + elif self == TableExportFormat.CSV: + return df.to_csv( + export_path, + sep=",", + index=with_index, + header=with_header, + float_format="%.6f", + ) + elif self == TableExportFormat.CSV_SEMICOLON: + return df.to_csv( + export_path, + sep=";", + decimal=",", + index=with_index, + header=with_header, + float_format="%.6f", + ) + elif self == TableExportFormat.HDF5: + return df.to_hdf( + export_path, + key="data", + mode="w", + format="table", + data_columns=True, + ) + else: # pragma: no cover + raise NotImplementedError(f"Export format '{self}' is not implemented") + + def create_raw_study_routes( study_service: StudyService, config: Config, @@ -88,7 +205,7 @@ def get_study( - `formatted`: A flag specifying whether the data should be returned in a formatted manner. Returns the fetched data: a JSON object (in most cases), a plain text file - or a file attachment (Microsoft Office document, CSV/TSV file...). + or a file attachment (Microsoft Office document, TSV/TSV file...). """ logger.info( f"📘 Fetching data at {path} (depth={depth}) from study {uuid}", @@ -99,10 +216,10 @@ def get_study( if isinstance(output, bytes): # Guess the suffix form the target data - resource_path = pathlib.PurePosixPath(path) + resource_path = PurePosixPath(path) parent_cfg = study_service.get(uuid, str(resource_path.parent), depth=2, formatted=True, params=parameters) child = parent_cfg[resource_path.name] - suffix = pathlib.PurePosixPath(child).suffix + suffix = PurePosixPath(child).suffix content_type, encoding = CONTENT_TYPES.get(suffix, (None, None)) if content_type == "application/json": @@ -152,6 +269,104 @@ def get_study( ).encode("utf-8") return Response(content=json_response, media_type="application/json") + @bp.get( + "/studies/{uuid}/areas/aggregate", + tags=[APITag.study_raw_data], + summary="Retrieve Aggregated Areas Raw Data from Study Output", + ) + def aggregate_areas_raw_data( + uuid: str, + output_id: str, + query_file: AreasQueryFile, + frequency: MatrixFrequency, + mc_years: str = "", + areas_ids: str = "", + columns_names: str = "", + current_user: JWTUser = Depends(auth.get_current_user), + ) -> t.Dict[str, t.Any]: + """ + Create an aggregation of areas raw data + + Args: + uuid: study ID + output_id: the output ID aka the simulation ID + query_file: "values", "details", "details-st-storage", "details-res" + frequency: "hourly", "daily", "weekly", "monthly", "annual" + mc_years: which Monte Carlo years to be selected if empty all are selected (comma separated) + areas_ids: which areas to be selected if empty all are selected (comma separated) + columns_names: which columns to be selected if empty all are selected (comma separated) + current_user: the current user login info + + + Returns: + JSON (DF like matrix) object with the aggregated raw output data for areas + + """ + logger.info( + f"Aggregate areas raw data at {query_file} (output name = {output_id}) from study {uuid}", + extra={"user": current_user.id}, + ) + parameters = RequestParameters(user=current_user) + output = study_service.aggregate_areas_data( + uuid, + output_id=output_id, + query_file=query_file, + frequency=frequency, + mc_years=[int(mc_year) for mc_year in _split_comma_separated_values(mc_years)], + areas_ids=_split_comma_separated_values(areas_ids), + columns_names=_split_comma_separated_values(columns_names), + params=parameters, + ) + + return output + + @bp.get( + "/studies/{uuid}/links/aggregate", + tags=[APITag.study_raw_data], + summary="Retrieve Aggregated Areas Raw Data from Study Output", + ) + def aggregate_links_raw_data( + uuid: str, + output_id: str, + query_file: LinksQueryFile, + frequency: MatrixFrequency, + mc_years: str = "", + columns_names: str = "", + current_user: JWTUser = Depends(auth.get_current_user), + ) -> t.Dict[str, t.Any]: + """ + Create an aggregation of links raw data + + Args: + uuid: study ID + output_id: the output ID aka the simulation ID + query_file: "values", "details" + frequency: "hourly", "daily", "weekly", "monthly", "annual" + mc_years: which Monte Carlo years to be selected if empty all are selected (comma separated) + columns_names: which columns to be selected if empty all are selected (comma separated) + current_user: the current user login info + + Returns: + JSON (DF like matrix) with the aggregated links raw data + + """ + logger.info( + f"Aggregate links raw data at {query_file} (output name = {output_id}) from study {uuid}", + extra={"user": current_user.id}, + ) + parameters = RequestParameters(user=current_user) + output = study_service.aggregate_links_data( + uuid, + output_id=output_id, + query_file=query_file, + frequency=frequency, + mc_years=[int(mc_year) for mc_year in _split_comma_separated_values(mc_years)], + columns_names=_split_comma_separated_values(columns_names), + params=parameters, + ) + + return output + @bp.post( "/studies/{uuid}/raw", status_code=http.HTTPStatus.NO_CONTENT, @@ -243,4 +458,70 @@ def validate( ) return study_service.check_errors(uuid) + @bp.get( + "/studies/{uuid}/raw/download", + summary="Download a matrix in a given format", + tags=[APITag.study_raw_data], + ) + def get_matrix( + uuid: str, + matrix_path: str = Query( # type: ignore + ..., alias="path", description="Relative path of the matrix to download", title="Matrix Path" + ), + export_format: TableExportFormat = Query( # type: ignore + TableExportFormat.XLSX, alias="format", description="Export format", title="Export Format" + ), + with_header: bool = Query( # type: ignore + True, alias="header", description="Whether to include the header or not", title="With Header" + ), + with_index: bool = Query( # type: ignore + True, alias="index", description="Whether to include the index or not", title="With Index" + ), + current_user: JWTUser = Depends(auth.get_current_user), + ) -> FileResponse: + parameters = RequestParameters(user=current_user) + df_matrix = study_service.get_matrix_with_index_and_header( + study_id=uuid, + path=matrix_path, + with_index=with_index, + with_header=with_header, + parameters=parameters, + ) + + matrix_name = Path(matrix_path).stem + export_file_download = study_service.file_transfer_manager.request_download( + f"{matrix_name}{export_format.suffix}", + f"Exporting matrix '{matrix_name}' to {export_format} format for study '{uuid}'", + current_user, + use_notification=False, + expiration_time_in_minutes=10, + ) + export_path = Path(export_file_download.path) + export_id = export_file_download.id + + try: + export_format.export_table(df_matrix, export_path, with_index=with_index, with_header=with_header) + study_service.file_transfer_manager.set_ready(export_id, use_notification=False) + except ValueError as e: + study_service.file_transfer_manager.fail(export_id, str(e)) + raise HTTPException( + status_code=http.HTTPStatus.UNPROCESSABLE_ENTITY, + detail=f"Cannot replace '{export_path}' due to Excel policy: {e}", + ) from e + except FileDownloadNotFound as e: + study_service.file_transfer_manager.fail(export_id, str(e)) + raise HTTPException( + status_code=http.HTTPStatus.UNPROCESSABLE_ENTITY, + detail=f"The file download does not exist in database :{str(e)}", + ) from e + + return FileResponse( + export_path, + headers={ + "Content-Disposition": f'attachment; filename="{export_file_download.filename}"', + "Content-Type": f"{export_format.media_type}; charset=utf-8", + }, + media_type=export_format.media_type, + ) + return bp diff --git a/antarest/study/web/studies_blueprint.py b/antarest/study/web/studies_blueprint.py index beeecd65c5..1945f71ab4 100644 --- a/antarest/study/web/studies_blueprint.py +++ b/antarest/study/web/studies_blueprint.py @@ -15,7 +15,7 @@ from antarest.core.filetransfer.service import FileTransferManager from antarest.core.jwt import JWTUser from antarest.core.model import PublicMode -from antarest.core.requests import RequestParameters +from antarest.core.requests import RequestParameters, UserHasNotPermissionError from antarest.core.utils.utils import BadArchiveContent, sanitize_uuid from antarest.core.utils.web import APITag from antarest.login.auth import Auth @@ -28,12 +28,14 @@ StudyMetadataPatchDTO, StudySimResultDTO, ) -from antarest.study.repository import StudyFilter, StudyPagination, StudySortBy +from antarest.study.repository import AccessPermissions, StudyFilter, StudyPagination, StudySortBy from antarest.study.service import StudyService from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfigDTO logger = logging.getLogger(__name__) +QUERY_REGEX = r"^\s*(?:\d+\s*(?:,\s*\d+\s*)*)?$" + def _split_comma_separated_values(value: str, *, default: t.Sequence[str] = ()) -> t.Sequence[str]: """Split a comma-separated list of values into an ordered set of strings.""" @@ -76,49 +78,30 @@ def get_studies( managed: t.Optional[bool] = Query(None, description="Filter studies based on their management status."), archived: t.Optional[bool] = Query(None, description="Filter studies based on their archive status."), variant: t.Optional[bool] = Query(None, description="Filter studies based on their variant status."), - versions: str = Query( - "", - description="Comma-separated list of versions for filtering.", - regex=r"^\s*(?:\d+\s*(?:,\s*\d+\s*)*)?$", - ), - users: str = Query( - "", - description="Comma-separated list of user IDs for filtering.", - regex=r"^\s*(?:\d+\s*(?:,\s*\d+\s*)*)?$", - ), + versions: str = Query("", description="Comma-separated list of versions for filtering.", regex=QUERY_REGEX), + users: str = Query("", description="Comma-separated list of user IDs for filtering.", regex=QUERY_REGEX), groups: str = Query("", description="Comma-separated list of group IDs for filtering."), tags: str = Query("", description="Comma-separated list of tags for filtering."), - study_ids: str = Query( - "", - description="Comma-separated list of study IDs for filtering.", - alias="studyIds", - ), + study_ids: str = Query("", description="Comma-separated list of study IDs for filtering.", alias="studyIds"), exists: t.Optional[bool] = Query(None, description="Filter studies based on their existence on disk."), workspace: str = Query("", description="Filter studies based on their workspace."), folder: str = Query("", description="Filter studies based on their folder."), - # It is advisable to use an optional Query parameter for enumerated types, like booleans. sort_by: t.Optional[StudySortBy] = Query( None, description="Sort studies based on their name (case-insensitive) or creation date.", alias="sortBy", ), - page_nb: NonNegativeInt = Query( - 0, - description="Page number (starting from 0).", - alias="pageNb", - ), + page_nb: NonNegativeInt = Query(0, description="Page number (starting from 0).", alias="pageNb"), page_size: NonNegativeInt = Query( - 0, - description="Number of studies per page (0 = no limit).", - alias="pageSize", + 0, description="Number of studies per page (0 = no limit).", alias="pageSize" ), ) -> t.Dict[str, StudyMetadataDTO]: """ Get the list of studies matching the specified criteria. Args: + - `name`: Filter studies based on their name. Case-insensitive search for studies - whose name contains the specified value. - `managed`: Filter studies based on their management status. - `archived`: Filter studies based on their archive status. - `variant`: Filter studies based on their variant status. @@ -144,6 +127,9 @@ def get_studies( user_list = [int(v) for v in _split_comma_separated_values(users)] + if not params.user: + raise UserHasNotPermissionError("FAIL permission: user is not logged") + study_filter = StudyFilter( name=name, managed=managed, @@ -157,10 +143,10 @@ def get_studies( exists=exists, workspace=workspace, folder=folder, + access_permissions=AccessPermissions.from_params(params), ) matching_studies = study_service.get_studies_information( - params=params, study_filter=study_filter, sort_by=sort_by, pagination=StudyPagination(page_nb=page_nb, page_size=page_size), @@ -168,6 +154,76 @@ def get_studies( return matching_studies + @bp.get( + "/studies/count", + tags=[APITag.study_management], + summary="Count Studies", + ) + def count_studies( + current_user: JWTUser = Depends(auth.get_current_user), + name: str = Query("", description="Case-insensitive: filter studies based on their name.", alias="name"), + managed: t.Optional[bool] = Query(None, description="Management status filter."), + archived: t.Optional[bool] = Query(None, description="Archive status filter."), + variant: t.Optional[bool] = Query(None, description="Variant status filter."), + versions: str = Query("", description="Comma-separated versions filter.", regex=QUERY_REGEX), + users: str = Query("", description="Comma-separated user IDs filter.", regex=QUERY_REGEX), + groups: str = Query("", description="Comma-separated group IDs filter."), + tags: str = Query("", description="Comma-separated tags filter."), + study_ids: str = Query("", description="Comma-separated study IDs filter.", alias="studyIds"), + exists: t.Optional[bool] = Query(None, description="Existence on disk filter."), + workspace: str = Query("", description="Workspace filter."), + folder: str = Query("", description="Study folder filter."), + ) -> int: + """ + Get the number of studies matching the specified criteria. + + Args: + + - `name`: Regexp to filter through studies based on their names + - `managed`: Whether to limit the selection based on management status. + - `archived`: Whether to limit the selection based on archive status. + - `variant`: Whether to limit the selection either raw or variant studies. + - `versions`: Comma-separated versions for studies to be selected. + - `users`: Comma-separated user IDs for studies to be selected. + - `groups`: Comma-separated group IDs for studies to be selected. + - `tags`: Comma-separated tags for studies to be selected. + - `studyIds`: Comma-separated IDs of studies to be selected. + - `exists`: Whether to limit the selection based on studies' existence on disk. + - `workspace`: to limit studies selection based on their workspace. + - `folder`: to limit studies selection based on their folder. + + Returns: + - An integer representing the total number of studies matching the filters above and the user permissions. + """ + + logger.info("Counting matching studies", extra={"user": current_user.id}) + params = RequestParameters(user=current_user) + + user_list = [int(v) for v in _split_comma_separated_values(users)] + + if not params.user: + raise UserHasNotPermissionError("FAIL permission: user is not logged") + + count = study_service.count_studies( + study_filter=StudyFilter( + name=name, + managed=managed, + archived=archived, + variant=variant, + versions=_split_comma_separated_values(versions), + users=user_list, + groups=_split_comma_separated_values(groups), + tags=_split_comma_separated_values(tags), + study_ids=_split_comma_separated_values(study_ids), + exists=exists, + workspace=workspace, + folder=folder, + access_permissions=AccessPermissions.from_params(params), + ), + ) + + return count + @bp.get( "/studies/{uuid}/comments", tags=[APITag.study_management], diff --git a/antarest/study/web/study_data_blueprint.py b/antarest/study/web/study_data_blueprint.py index ddc38ef60d..467aa49805 100644 --- a/antarest/study/web/study_data_blueprint.py +++ b/antarest/study/web/study_data_blueprint.py @@ -1,15 +1,15 @@ import enum import logging +import typing as t from http import HTTPStatus -from typing import Any, Dict, List, Optional, Sequence, Union, cast -from fastapi import APIRouter, Body, Depends -from fastapi.params import Query +import typing_extensions as te +from fastapi import APIRouter, Body, Depends, Query from starlette.responses import RedirectResponse from antarest.core.config import Config from antarest.core.jwt import JWTUser -from antarest.core.model import StudyPermissionType +from antarest.core.model import JSON, StudyPermissionType from antarest.core.requests import RequestParameters from antarest.core.utils.utils import sanitize_uuid from antarest.core.utils.web import APITag @@ -18,7 +18,7 @@ from antarest.study.business.adequacy_patch_management import AdequacyPatchFormFields from antarest.study.business.advanced_parameters_management import AdvancedParamsFormFields from antarest.study.business.allocation_management import AllocationFormFields, AllocationMatrix -from antarest.study.business.area_management import AreaCreationDTO, AreaInfoDTO, AreaType, AreaUI, LayerInfoDTO +from antarest.study.business.area_management import AreaCreationDTO, AreaInfoDTO, AreaType, LayerInfoDTO, UpdateAreaUi from antarest.study.business.areas.hydro_management import InflowStructure, ManagementOptionsFormFields from antarest.study.business.areas.properties_management import PropertiesFormFields from antarest.study.business.areas.renewable_management import ( @@ -42,9 +42,11 @@ ThermalManager, ) from antarest.study.business.binding_constraint_management import ( - BindingConstraintPropertiesWithName, - ConstraintTermDTO, - UpdateBindingConstProps, + ConstraintCreation, + ConstraintFilters, + ConstraintInput, + ConstraintOutput, + ConstraintTerm, ) from antarest.study.business.correlation_management import CorrelationFormFields, CorrelationManager, CorrelationMatrix from antarest.study.business.district_manager import DistrictCreationDTO, DistrictInfoDTO, DistrictUpdateDTO @@ -52,16 +54,27 @@ from antarest.study.business.link_management import LinkInfoDTO from antarest.study.business.optimization_management import OptimizationFormFields from antarest.study.business.playlist_management import PlaylistColumns -from antarest.study.business.table_mode_management import ColumnsModelTypes, TableTemplateType +from antarest.study.business.table_mode_management import TableDataDTO, TableModeType from antarest.study.business.thematic_trimming_field_infos import ThematicTrimmingFormFields from antarest.study.business.timeseries_config_management import TSFormFields from antarest.study.model import PatchArea, PatchCluster from antarest.study.service import StudyService +from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import ( + BindingConstraintFrequency, + BindingConstraintOperator, +) from antarest.study.storage.rawstudy.model.filesystem.config.model import transform_name_to_id logger = logging.getLogger(__name__) +class BCKeyValueType(te.TypedDict): + """Deprecated type for binding constraint key-value pair (used for update)""" + + key: str + value: t.Union[str, int, float, bool] + + class ClusterType(str, enum.Enum): """ Cluster type: @@ -95,14 +108,14 @@ def create_study_data_routes(study_service: StudyService, config: Config) -> API "/studies/{uuid}/areas", tags=[APITag.study_data], summary="Get all areas basic info", - response_model=Union[List[AreaInfoDTO], Dict[str, Any]], # type: ignore + response_model=t.Union[t.List[AreaInfoDTO], t.Dict[str, t.Any]], # type: ignore ) def get_areas( uuid: str, - type: Optional[AreaType] = None, + type: t.Optional[AreaType] = None, ui: bool = False, current_user: JWTUser = Depends(auth.get_current_user), - ) -> Union[List[AreaInfoDTO], Dict[str, Any]]: + ) -> t.Union[t.List[AreaInfoDTO], t.Dict[str, t.Any]]: logger.info( f"Fetching area list (type={type}) for study {uuid}", extra={"user": current_user.id}, @@ -115,13 +128,13 @@ def get_areas( "/studies/{uuid}/links", tags=[APITag.study_data], summary="Get all links", - response_model=List[LinkInfoDTO], + response_model=t.List[LinkInfoDTO], ) def get_links( uuid: str, with_ui: bool = False, current_user: JWTUser = Depends(auth.get_current_user), - ) -> Any: + ) -> t.Any: logger.info( f"Fetching link list for study {uuid}", extra={"user": current_user.id}, @@ -140,7 +153,7 @@ def create_area( uuid: str, area_creation_info: AreaCreationDTO, current_user: JWTUser = Depends(auth.get_current_user), - ) -> Any: + ) -> t.Any: logger.info( f"Creating new area for study {uuid}", extra={"user": current_user.id}, @@ -158,7 +171,7 @@ def create_link( uuid: str, link_creation_info: LinkInfoDTO, current_user: JWTUser = Depends(auth.get_current_user), - ) -> Any: + ) -> t.Any: logger.info( f"Creating new link for study {uuid}", extra={"user": current_user.id}, @@ -175,10 +188,10 @@ def create_link( def update_area_ui( uuid: str, area_id: str, - area_ui: AreaUI, + area_ui: UpdateAreaUi, layer: str = "0", current_user: JWTUser = Depends(auth.get_current_user), - ) -> Any: + ) -> t.Any: logger.info( f"Updating area ui {area_id} for study {uuid}", extra={"user": current_user.id}, @@ -195,9 +208,9 @@ def update_area_ui( def update_area_info( uuid: str, area_id: str, - area_patch_dto: Union[PatchArea, Dict[str, PatchCluster]], + area_patch_dto: t.Union[PatchArea, t.Dict[str, PatchCluster]], current_user: JWTUser = Depends(auth.get_current_user), - ) -> Any: + ) -> t.Any: logger.info( f"Updating area {area_id} for study {uuid}", extra={"user": current_user.id}, @@ -223,7 +236,7 @@ def delete_area( uuid: str, area_id: str, current_user: JWTUser = Depends(auth.get_current_user), - ) -> Any: + ) -> t.Any: logger.info( f"Removing area {area_id} in study {uuid}", extra={"user": current_user.id}, @@ -245,7 +258,7 @@ def delete_link( area_from: str, area_to: str, current_user: JWTUser = Depends(auth.get_current_user), - ) -> Any: + ) -> t.Any: logger.info( f"Removing link {area_from}%{area_to} in study {uuid}", extra={"user": current_user.id}, @@ -260,12 +273,12 @@ def delete_link( "/studies/{uuid}/layers", tags=[APITag.study_data], summary="Get all layers info", - response_model=List[LayerInfoDTO], + response_model=t.List[LayerInfoDTO], ) def get_layers( uuid: str, current_user: JWTUser = Depends(auth.get_current_user), - ) -> List[LayerInfoDTO]: + ) -> t.List[LayerInfoDTO]: logger.info( f"Fetching layer list for study {uuid}", extra={"user": current_user.id}, @@ -302,7 +315,7 @@ def update_layer( uuid: str, layer_id: str, name: str = "", - areas: Optional[List[str]] = None, + areas: t.Optional[t.List[str]] = None, current_user: JWTUser = Depends(auth.get_current_user), ) -> None: logger.info( @@ -340,12 +353,12 @@ def remove_layer( "/studies/{uuid}/districts", tags=[APITag.study_data], summary="Get the list of districts defined in this study", - response_model=List[DistrictInfoDTO], + response_model=t.List[DistrictInfoDTO], ) def get_districts( uuid: str, current_user: JWTUser = Depends(auth.get_current_user), - ) -> List[DistrictInfoDTO]: + ) -> t.List[DistrictInfoDTO]: logger.info( f"Fetching districts list for study {uuid}", extra={"user": current_user.id}, @@ -441,7 +454,7 @@ def set_hydro_form_values( area_id: str, data: ManagementOptionsFormFields, current_user: JWTUser = Depends(auth.get_current_user), - ) -> Any: + ) -> t.Any: logger.info( msg=f"Updating Hydro management config for area {area_id} of study {uuid}", extra={"user": current_user.id}, @@ -501,9 +514,9 @@ def update_inflow_structure( def edit_matrix( uuid: str, path: str, - matrix_edit_instructions: List[MatrixEditInstruction] = Body(...), + matrix_edit_instructions: t.List[MatrixEditInstruction] = Body(...), current_user: JWTUser = Depends(auth.get_current_user), - ) -> Any: + ) -> t.Any: # NOTE: This Markdown documentation is reflected in the Swagger API """ Edit a matrix in a study based on the provided edit instructions. @@ -560,13 +573,13 @@ def set_thematic_trimming( path="/studies/{uuid}/config/playlist/form", tags=[APITag.study_data], summary="Get MC Scenario playlist data for table form", - response_model=Dict[int, PlaylistColumns], + response_model=t.Dict[int, PlaylistColumns], response_model_exclude_none=True, ) def get_playlist( uuid: str, current_user: JWTUser = Depends(auth.get_current_user), - ) -> Dict[int, PlaylistColumns]: + ) -> t.Dict[int, PlaylistColumns]: logger.info( f"Getting MC Scenario playlist data for study {uuid}", extra={"user": current_user.id}, @@ -583,7 +596,7 @@ def get_playlist( ) def set_playlist( uuid: str, - data: Dict[int, PlaylistColumns], + data: t.Dict[int, PlaylistColumns], current_user: JWTUser = Depends(auth.get_current_user), ) -> None: logger.info( @@ -598,12 +611,12 @@ def set_playlist( "/studies/{uuid}/config/playlist", tags=[APITag.study_data], summary="Get playlist config", - response_model=Dict[int, float], + response_model=t.Dict[int, float], ) def get_playlist_config( uuid: str, current_user: JWTUser = Depends(auth.get_current_user), - ) -> Any: + ) -> t.Any: logger.info( f"Fetching playlist config for study {uuid}", extra={"user": current_user.id}, @@ -621,10 +634,10 @@ def set_playlist_config( uuid: str, active: bool = True, reverse: bool = False, - playlist: Optional[List[int]] = Body(default=None), - weights: Optional[Dict[int, int]] = Body(default=None), + playlist: t.Optional[t.List[int]] = Body(default=None), + weights: t.Optional[t.Dict[int, int]] = Body(default=None), current_user: JWTUser = Depends(auth.get_current_user), - ) -> Any: + ) -> t.Any: logger.info( f"Updating playlist config for study {uuid}", extra={"user": current_user.id}, @@ -637,12 +650,12 @@ def set_playlist_config( path="/studies/{uuid}/config/scenariobuilder", tags=[APITag.study_data], summary="Get MC Scenario builder config", - response_model=Dict[str, Any], + response_model=t.Dict[str, t.Any], ) def get_scenario_builder_config( uuid: str, current_user: JWTUser = Depends(auth.get_current_user), - ) -> Dict[str, Any]: + ) -> t.Dict[str, t.Any]: logger.info( f"Getting MC Scenario builder config for study {uuid}", extra={"user": current_user.id}, @@ -659,7 +672,7 @@ def get_scenario_builder_config( ) def update_scenario_builder_config( uuid: str, - data: Dict[str, Any], + data: t.Dict[str, t.Any], current_user: JWTUser = Depends(auth.get_current_user), ) -> None: logger.info( @@ -827,47 +840,95 @@ def set_timeseries_form_values( study_service.ts_config_manager.set_field_values(study, field_values) @bp.get( - path="/studies/{uuid}/tablemode", + path="/table-schema/{table_type}", + tags=[APITag.study_data], + summary="Get table schema", + ) + def get_table_schema( + table_type: TableModeType, + current_user: JWTUser = Depends(auth.get_current_user), + ) -> JSON: + """ + Get the properties of the table columns. + + Args: + - `table_type`: The type of table to get the schema for. + """ + logger.info("Getting table schema", extra={"user": current_user.id}) + model_schema = study_service.table_mode_manager.get_table_schema(table_type) + return model_schema + + @bp.get( + path="/studies/{uuid}/table-mode/{table_type}", tags=[APITag.study_data], summary="Get table data for table form", - # `Any` because `Union[AreaColumns, LinkColumns]` not working - response_model=Dict[str, Dict[str, Any]], - response_model_exclude_none=True, ) def get_table_mode( uuid: str, - table_type: TableTemplateType, - columns: str, + table_type: TableModeType, + columns: str = Query("", description="A comma-separated list of columns to include in the table data"), current_user: JWTUser = Depends(auth.get_current_user), - ) -> Dict[str, ColumnsModelTypes]: + ) -> TableDataDTO: + """ + Get the table data for the given study and table type. + + Args: + - uuid: The UUID of the study. + - table_type: The type of table to get the data for. + """ logger.info( - f"Getting template table data for study {uuid}", + f"Getting table data for study {uuid}", extra={"user": current_user.id}, ) params = RequestParameters(user=current_user) study = study_service.check_study_access(uuid, StudyPermissionType.READ, params) - - return study_service.table_mode_manager.get_table_data(study, table_type, columns.split(",")) + column_list = columns.split(",") if columns else [] + table_data = study_service.table_mode_manager.get_table_data(study, table_type, column_list) + return table_data @bp.put( - path="/studies/{uuid}/tablemode", + path="/studies/{uuid}/table-mode/{table_type}", tags=[APITag.study_data], - summary="Set table data with values from table form", + summary="Update table data with values from table form", ) - def set_table_mode( + def update_table_mode( uuid: str, - table_type: TableTemplateType, - data: Dict[str, ColumnsModelTypes], + table_type: TableModeType, + data: TableDataDTO = Body( + ..., + example={ + "de / nuclear_cl1": { + "enabled": True, + "group": "Nuclear", + "unitCount": 17, + "nominalCapacity": 123, + }, + "de / gas_cl1": { + "enabled": True, + "group": "Gas", + "unitCount": 15, + "nominalCapacity": 456, + }, + }, + ), current_user: JWTUser = Depends(auth.get_current_user), - ) -> None: + ) -> TableDataDTO: + """ + Update the table data for the given study and table type. + + Args: + - uuid: The UUID of the study. + - table_type: The type of table to update. + - data: The table data to update. + """ logger.info( f"Updating table data for study {uuid}", extra={"user": current_user.id}, ) params = RequestParameters(user=current_user) study = study_service.check_study_access(uuid, StudyPermissionType.WRITE, params) - - study_service.table_mode_manager.set_table_data(study, table_type, data) + table_data = study_service.table_mode_manager.update_table_data(study, table_type, data) + return table_data @bp.post( "/studies/_update_version", @@ -876,7 +937,7 @@ def set_table_mode( ) def update_version( current_user: JWTUser = Depends(auth.get_current_user), - ) -> Any: + ) -> t.Any: params = RequestParameters(user=current_user) study_service.check_and_update_all_study_versions_in_database(params) @@ -884,31 +945,71 @@ def update_version( "/studies/{uuid}/bindingconstraints", tags=[APITag.study_data], summary="Get binding constraint list", - response_model=None, # Dict[str, bool], + response_model=t.List[ConstraintOutput], ) def get_binding_constraint_list( uuid: str, + enabled: t.Optional[bool] = Query(None, description="Filter results based on enabled status"), + operator: t.Optional[BindingConstraintOperator] = Query(None, description="Filter results based on operator"), + comments: str = Query("", description="Filter results based on comments (word match)"), + group: str = Query("", description="filter binding constraints based on group name (exact match)"), + time_step: t.Optional[BindingConstraintFrequency] = Query( + None, + description="Filter results based on time step", + alias="timeStep", + ), + area_name: str = Query( + "", + description="Filter results based on area name (word match)", + alias="areaName", + ), + cluster_name: str = Query( + "", + description="Filter results based on cluster name (word match)", + alias="clusterName", + ), + link_id: str = Query( + "", + description="Filter results based on link ID ('area1%area2')", + alias="linkId", + ), + cluster_id: str = Query( + "", + description="Filter results based on cluster ID ('area.cluster')", + alias="clusterId", + ), current_user: JWTUser = Depends(auth.get_current_user), - ) -> Any: + ) -> t.Sequence[ConstraintOutput]: logger.info( f"Fetching binding constraint list for study {uuid}", extra={"user": current_user.id}, ) params = RequestParameters(user=current_user) study = study_service.check_study_access(uuid, StudyPermissionType.READ, params) - return study_service.binding_constraint_manager.get_binding_constraint(study, None) + filters = ConstraintFilters( + enabled=enabled, + operator=operator, + comments=comments, + group=group, + time_step=time_step, + area_name=area_name, + cluster_name=cluster_name, + link_id=link_id, + cluster_id=cluster_id, + ) + return study_service.binding_constraint_manager.get_binding_constraints(study, filters) @bp.get( "/studies/{uuid}/bindingconstraints/{binding_constraint_id}", tags=[APITag.study_data], summary="Get binding constraint", - response_model=None, # Dict[str, bool], + response_model=ConstraintOutput, # type: ignore ) def get_binding_constraint( uuid: str, binding_constraint_id: str, current_user: JWTUser = Depends(auth.get_current_user), - ) -> Any: + ) -> ConstraintOutput: logger.info( f"Fetching binding constraint {binding_constraint_id} for study {uuid}", extra={"user": current_user.id}, @@ -921,14 +1022,13 @@ def get_binding_constraint( "/studies/{uuid}/bindingconstraints/{binding_constraint_id}", tags=[APITag.study_data], summary="Update binding constraint", - response_model=None, # Dict[str, bool], ) def update_binding_constraint( uuid: str, binding_constraint_id: str, - data: UpdateBindingConstProps, + data: ConstraintInput, current_user: JWTUser = Depends(auth.get_current_user), - ) -> Any: + ) -> ConstraintOutput: logger.info( f"Update binding constraint {binding_constraint_id} for study {uuid}", extra={"user": current_user.id}, @@ -937,15 +1037,137 @@ def update_binding_constraint( study = study_service.check_study_access(uuid, StudyPermissionType.WRITE, params) return study_service.binding_constraint_manager.update_binding_constraint(study, binding_constraint_id, data) - @bp.post( - "/studies/{uuid}/bindingconstraints", + @bp.get( + "/studies/{uuid}/constraint-groups", tags=[APITag.study_data], - summary="Create a binding constraint", + summary="Get the list of binding constraint groups", + ) + def get_grouped_constraints( + uuid: str, + current_user: JWTUser = Depends(auth.get_current_user), + ) -> t.Mapping[str, t.Sequence[ConstraintOutput]]: + """ + Get the list of binding constraint groups for the study. + + Args: + - `uuid`: The UUID of the study. + + Returns: + - The list of binding constraints for each group. + """ + logger.info( + f"Fetching binding constraint groups for study {uuid}", + extra={"user": current_user.id}, + ) + params = RequestParameters(user=current_user) + study = study_service.check_study_access(uuid, StudyPermissionType.READ, params) + result = study_service.binding_constraint_manager.get_grouped_constraints(study) + return result + + @bp.get( + # We use "validate-all" because it is unlikely to conflict with a group name. + "/studies/{uuid}/constraint-groups/validate-all", + tags=[APITag.study_data], + summary="Validate all binding constraint groups", response_model=None, ) + def validate_constraint_groups( + uuid: str, + current_user: JWTUser = Depends(auth.get_current_user), + ) -> bool: + """ + Checks if the dimensions of the right-hand side matrices are consistent with + the dimensions of the binding constraint matrices within the same group. + + Args: + - `uuid`: The study UUID. + + Returns: + - `true` if all groups are valid. + + Raises: + - HTTPException(422) if any group is invalid. + """ + logger.info( + f"Validating all binding constraint groups for study {uuid}", + extra={"user": current_user.id}, + ) + params = RequestParameters(user=current_user) + study = study_service.check_study_access(uuid, StudyPermissionType.READ, params) + return study_service.binding_constraint_manager.validate_constraint_groups(study) + + @bp.get( + "/studies/{uuid}/constraint-groups/{group}", + tags=[APITag.study_data], + summary="Get the binding constraint group", + ) + def get_constraints_by_group( + uuid: str, + group: str, + current_user: JWTUser = Depends(auth.get_current_user), + ) -> t.Sequence[ConstraintOutput]: + """ + Get the binding constraint group for the study. + + Args: + - `uuid`: The UUID of the study. + - `group`: The name of the binding constraint group (case-insensitive). + + Returns: + - The list of binding constraints in the group. + + Raises: + - HTTPException(404) if the group does not exist. + """ + logger.info( + f"Fetching binding constraint group '{group}' for study {uuid}", + extra={"user": current_user.id}, + ) + params = RequestParameters(user=current_user) + study = study_service.check_study_access(uuid, StudyPermissionType.READ, params) + result = study_service.binding_constraint_manager.get_constraints_by_group(study, group) + return result + + @bp.get( + "/studies/{uuid}/constraint-groups/{group}/validate", + tags=[APITag.study_data], + summary="Validate the binding constraint group", + response_model=None, + ) + def validate_constraint_group( + uuid: str, + group: str, + current_user: JWTUser = Depends(auth.get_current_user), + ) -> bool: + """ + Checks if the dimensions of the right-hand side matrices are consistent with + the dimensions of the binding constraint matrices within the same group. + + Args: + - `uuid`: The study UUID. + - `group`: The name of the binding constraint group (case-insensitive). + + Returns: + - `true` if the group is valid. + + Raises: + - HTTPException(404) if the group does not exist. + - HTTPException(422) if the group is invalid. + """ + logger.info( + f"Validating binding constraint group '{group}' for study {uuid}", + extra={"user": current_user.id}, + ) + params = RequestParameters(user=current_user) + study = study_service.check_study_access(uuid, StudyPermissionType.READ, params) + return study_service.binding_constraint_manager.validate_constraint_group(study, group) + + @bp.post("/studies/{uuid}/bindingconstraints", tags=[APITag.study_data], summary="Create a binding constraint") def create_binding_constraint( - uuid: str, data: BindingConstraintPropertiesWithName, current_user: JWTUser = Depends(auth.get_current_user) - ) -> None: + uuid: str, + data: ConstraintCreation, + current_user: JWTUser = Depends(auth.get_current_user), + ) -> ConstraintOutput: logger.info( f"Creating a new binding constraint for study {uuid}", extra={"user": current_user.id}, @@ -954,6 +1176,23 @@ def create_binding_constraint( study = study_service.check_study_access(uuid, StudyPermissionType.READ, params) return study_service.binding_constraint_manager.create_binding_constraint(study, data) + @bp.delete( + "/studies/{uuid}/bindingconstraints/{binding_constraint_id}", + tags=[APITag.study_data], + summary="Delete a binding constraint", + response_model=None, + ) + def delete_binding_constraint( + uuid: str, binding_constraint_id: str, current_user: JWTUser = Depends(auth.get_current_user) + ) -> None: + logger.info( + f"Deleting the binding constraint {binding_constraint_id} for study {uuid}", + extra={"user": current_user.id}, + ) + params = RequestParameters(user=current_user) + study = study_service.check_study_access(uuid, StudyPermissionType.WRITE, params) + return study_service.binding_constraint_manager.remove_binding_constraint(study, binding_constraint_id) + @bp.post( "/studies/{uuid}/bindingconstraints/{binding_constraint_id}/term", tags=[APITag.study_data], @@ -962,16 +1201,51 @@ def create_binding_constraint( def add_constraint_term( uuid: str, binding_constraint_id: str, - term: ConstraintTermDTO, + term: ConstraintTerm, current_user: JWTUser = Depends(auth.get_current_user), - ) -> Any: + ) -> None: + """ + Append a new term to a given binding constraint + + Args: + - `uuid`: The UUID of the study. + - `binding_constraint_id`: The binding constraint ID. + - `term`: The term to create. + """ logger.info( f"Add constraint term {term.id} to {binding_constraint_id} for study {uuid}", extra={"user": current_user.id}, ) params = RequestParameters(user=current_user) study = study_service.check_study_access(uuid, StudyPermissionType.WRITE, params) - return study_service.binding_constraint_manager.add_new_constraint_term(study, binding_constraint_id, term) + return study_service.binding_constraint_manager.create_constraint_terms(study, binding_constraint_id, [term]) + + @bp.post( + "/studies/{uuid}/bindingconstraints/{binding_constraint_id}/terms", + tags=[APITag.study_data], + summary="Create terms for a given binding constraint", + ) + def add_constraint_terms( + uuid: str, + binding_constraint_id: str, + terms: t.Sequence[ConstraintTerm], + current_user: JWTUser = Depends(auth.get_current_user), + ) -> None: + """ + Append new terms to a given binding constraint + + Args: + - `uuid`: The UUID of the study. + - `binding_constraint_id`: The binding constraint ID. + - `terms`: The list of terms to create. + """ + logger.info( + f"Adding constraint terms to {binding_constraint_id} for study {uuid}", + extra={"user": current_user.id}, + ) + params = RequestParameters(user=current_user) + study = study_service.check_study_access(uuid, StudyPermissionType.WRITE, params) + return study_service.binding_constraint_manager.create_constraint_terms(study, binding_constraint_id, terms) @bp.put( "/studies/{uuid}/bindingconstraints/{binding_constraint_id}/term", @@ -981,16 +1255,51 @@ def add_constraint_term( def update_constraint_term( uuid: str, binding_constraint_id: str, - term: ConstraintTermDTO, + term: ConstraintTerm, current_user: JWTUser = Depends(auth.get_current_user), - ) -> Any: + ) -> None: + """ + Update a term for a given binding constraint + + Args: + - `uuid`: The UUID of the study. + - `binding_constraint_id`: The binding constraint ID. + - `term`: The term to update. + """ logger.info( f"Update constraint term {term.id} from {binding_constraint_id} for study {uuid}", extra={"user": current_user.id}, ) params = RequestParameters(user=current_user) study = study_service.check_study_access(uuid, StudyPermissionType.WRITE, params) - return study_service.binding_constraint_manager.update_constraint_term(study, binding_constraint_id, term) + return study_service.binding_constraint_manager.update_constraint_terms(study, binding_constraint_id, [term]) + + @bp.put( + "/studies/{uuid}/bindingconstraints/{binding_constraint_id}/terms", + tags=[APITag.study_data], + summary="Update terms for a given binding constraint", + ) + def update_constraint_terms( + uuid: str, + binding_constraint_id: str, + terms: t.Sequence[ConstraintTerm], + current_user: JWTUser = Depends(auth.get_current_user), + ) -> None: + """ + Update several terms for a given binding constraint + + Args: + - `uuid`: The UUID of the study. + - `binding_constraint_id`: The binding constraint ID. + - `terms`: The list of terms to update. + """ + logger.info( + f"Updating constraint terms from {binding_constraint_id} for study {uuid}", + extra={"user": current_user.id}, + ) + params = RequestParameters(user=current_user) + study = study_service.check_study_access(uuid, StudyPermissionType.WRITE, params) + return study_service.binding_constraint_manager.update_constraint_terms(study, binding_constraint_id, terms) @bp.delete( "/studies/{uuid}/bindingconstraints/{binding_constraint_id}/term/{term_id}", @@ -1024,7 +1333,7 @@ def get_allocation_matrix( """ Get the hydraulic allocation matrix for all areas. - Parameters: + Args: - `uuid`: The study UUID. Returns the data frame matrix, where: @@ -1034,8 +1343,8 @@ def get_allocation_matrix( """ params = RequestParameters(user=current_user) study = study_service.check_study_access(uuid, StudyPermissionType.READ, params) - all_areas = cast( - List[AreaInfoDTO], # because `ui=False` + all_areas = t.cast( + t.List[AreaInfoDTO], # because `ui=False` study_service.get_all_areas(uuid, area_type=AreaType.AREA, ui=False, params=params), ) return study_service.allocation_manager.get_allocation_matrix(study, all_areas) @@ -1054,7 +1363,7 @@ def get_allocation_form_fields( """ Get the form fields used for the allocation form. - Parameters: + Args: - `uuid`: The study UUID, - `area_id`: the area ID. @@ -1062,8 +1371,8 @@ def get_allocation_form_fields( """ params = RequestParameters(user=current_user) study = study_service.check_study_access(uuid, StudyPermissionType.READ, params) - all_areas = cast( - List[AreaInfoDTO], # because `ui=False` + all_areas = t.cast( + t.List[AreaInfoDTO], # because `ui=False` study_service.get_all_areas(uuid, area_type=AreaType.AREA, ui=False, params=params), ) return study_service.allocation_manager.get_allocation_form_fields(all_areas, study, area_id) @@ -1092,7 +1401,7 @@ def set_allocation_form_fields( """ Update the hydraulic allocation of a given area. - Parameters: + Args: - `uuid`: The study UUID, - `area_id`: the area ID. @@ -1100,8 +1409,8 @@ def set_allocation_form_fields( """ params = RequestParameters(user=current_user) study = study_service.check_study_access(uuid, StudyPermissionType.WRITE, params) - all_areas = cast( - List[AreaInfoDTO], # because `ui=False` + all_areas = t.cast( + t.List[AreaInfoDTO], # because `ui=False` study_service.get_all_areas(uuid, area_type=AreaType.AREA, ui=False, params=params), ) return study_service.allocation_manager.set_allocation_form_fields(all_areas, study, area_id, data) @@ -1114,7 +1423,7 @@ def set_allocation_form_fields( ) def get_correlation_matrix( uuid: str, - columns: Optional[str] = Query( + columns: t.Optional[str] = Query( None, examples={ "all areas": { @@ -1130,13 +1439,13 @@ def get_correlation_matrix( "value": "north,east", }, }, - ), # type: ignore + ), current_user: JWTUser = Depends(auth.get_current_user), ) -> CorrelationMatrix: """ Get the hydraulic/load/solar/wind correlation matrix of a study. - Parameters: + Args: - `uuid`: The UUID of the study. - `columns`: a filter on the area identifiers: - Use no parameter to select all areas. @@ -1150,8 +1459,8 @@ def get_correlation_matrix( """ params = RequestParameters(user=current_user) study = study_service.check_study_access(uuid, StudyPermissionType.READ, params) - all_areas = cast( - List[AreaInfoDTO], # because `ui=False` + all_areas = t.cast( + t.List[AreaInfoDTO], # because `ui=False` study_service.get_all_areas(uuid, area_type=AreaType.AREA, ui=False, params=params), ) manager = CorrelationManager(study_service.storage_service) @@ -1188,7 +1497,7 @@ def set_correlation_matrix( """ Set the hydraulic/load/solar/wind correlation matrix of a study. - Parameters: + Args: - `uuid`: The UUID of the study. - `index`: a list of all study areas. - `columns`: a list of selected production areas. @@ -1198,8 +1507,8 @@ def set_correlation_matrix( """ params = RequestParameters(user=current_user) study = study_service.check_study_access(uuid, StudyPermissionType.WRITE, params) - all_areas = cast( - List[AreaInfoDTO], # because `ui=False` + all_areas = t.cast( + t.List[AreaInfoDTO], # because `ui=False` study_service.get_all_areas(uuid, area_type=AreaType.AREA, ui=False, params=params), ) manager = CorrelationManager(study_service.storage_service) @@ -1219,7 +1528,7 @@ def get_correlation_form_fields( """ Get the form fields used for the correlation form. - Parameters: + Args: - `uuid`: The UUID of the study. - `area_id`: the area ID. @@ -1227,8 +1536,8 @@ def get_correlation_form_fields( """ params = RequestParameters(user=current_user) study = study_service.check_study_access(uuid, StudyPermissionType.READ, params) - all_areas = cast( - List[AreaInfoDTO], # because `ui=False` + all_areas = t.cast( + t.List[AreaInfoDTO], # because `ui=False` study_service.get_all_areas(uuid, area_type=AreaType.AREA, ui=False, params=params), ) manager = CorrelationManager(study_service.storage_service) @@ -1258,7 +1567,7 @@ def set_correlation_form_fields( """ Update the hydraulic/load/solar/wind correlation of a given area. - Parameters: + Args: - `uuid`: The UUID of the study. - `area_id`: the area ID. @@ -1266,8 +1575,8 @@ def set_correlation_form_fields( """ params = RequestParameters(user=current_user) study = study_service.check_study_access(uuid, StudyPermissionType.WRITE, params) - all_areas = cast( - List[AreaInfoDTO], # because `ui=False` + all_areas = t.cast( + t.List[AreaInfoDTO], # because `ui=False` study_service.get_all_areas(uuid, area_type=AreaType.AREA, ui=False, params=params), ) manager = CorrelationManager(study_service.storage_service) @@ -1321,7 +1630,7 @@ def set_advanced_parameters( def generate_timeseries( uuid: str, current_user: JWTUser = Depends(auth.get_current_user), - ) -> Any: + ) -> t.Any: logger.info( f"Generating timeseries for study {uuid}", extra={"user": current_user.id}, @@ -1383,13 +1692,13 @@ def set_properties_form_values( path="/studies/{uuid}/areas/{area_id}/clusters/renewable", tags=[APITag.study_data], summary="Get all renewable clusters", - response_model=Sequence[RenewableClusterOutput], + response_model=t.Sequence[RenewableClusterOutput], ) def get_renewable_clusters( uuid: str, area_id: str, current_user: JWTUser = Depends(auth.get_current_user), - ) -> Sequence[RenewableClusterOutput]: + ) -> t.Sequence[RenewableClusterOutput]: logger.info( "Getting renewable clusters for study %s and area %s", uuid, @@ -1457,7 +1766,7 @@ def create_renewable_cluster( - `cluster_data`: the properties used for creation: "name" and "group". - Returns: The properties of the newly-created renewable clusters. + Returns: The properties of the newly-created renewable cluster. """ logger.info( f"Creating renewable cluster for study '{uuid}' and area '{area_id}'", @@ -1515,7 +1824,7 @@ def redirect_update_renewable_cluster( def delete_renewable_clusters( uuid: str, area_id: str, - cluster_ids: Sequence[str], + cluster_ids: t.Sequence[str], current_user: JWTUser = Depends(auth.get_current_user), ) -> None: """ @@ -1538,13 +1847,13 @@ def delete_renewable_clusters( path="/studies/{uuid}/areas/{area_id}/clusters/thermal", tags=[APITag.study_data], summary="Get thermal clusters for a given area", - response_model=Sequence[ThermalClusterOutput], + response_model=t.Sequence[ThermalClusterOutput], ) def get_thermal_clusters( uuid: str, area_id: str, current_user: JWTUser = Depends(auth.get_current_user), - ) -> Sequence[ThermalClusterOutput]: + ) -> t.Sequence[ThermalClusterOutput]: """ Retrieve the list of thermal clusters for a specified area. @@ -1631,7 +1940,7 @@ def create_thermal_cluster( - `cluster_data`: the properties used for creation: "name" and "group". - Returns: The properties of the newly-created thermal clusters. + Returns: The properties of the newly-created thermal cluster. """ logger.info( f"Creating thermal cluster for study '{uuid}' and area '{area_id}'", @@ -1689,6 +1998,36 @@ def redirect_update_thermal_cluster( # We cannot perform redirection, because we have a PUT, where a PATCH is required. return update_thermal_cluster(uuid, area_id, cluster_id, cluster_data, current_user=current_user) + @bp.get( + path="/studies/{uuid}/areas/{area_id}/clusters/thermal/{cluster_id}/validate", + tags=[APITag.study_data], + summary="Validates the thermal cluster series", + ) + def validate_cluster_series( + uuid: str, + area_id: str, + cluster_id: str, + current_user: JWTUser = Depends(auth.get_current_user), + ) -> bool: + """ + Validate the consistency of all time series for the given thermal cluster. + + Args: + - `uuid`: The UUID of the study. + - `area_id`: the area ID. + - `cluster_id`: the ID of the thermal cluster. + + Permissions: + - User must have READ permission on the study. + """ + logger.info( + f"Validating thermal series values for study {uuid} and cluster {cluster_id}", + extra={"user": current_user.id}, + ) + params = RequestParameters(user=current_user) + study = study_service.check_study_access(uuid, StudyPermissionType.READ, params) + return study_service.thermal_manager.validate_series(study, area_id, cluster_id) + @bp.delete( path="/studies/{uuid}/areas/{area_id}/clusters/thermal", tags=[APITag.study_data], @@ -1699,7 +2038,7 @@ def redirect_update_thermal_cluster( def delete_thermal_clusters( uuid: str, area_id: str, - cluster_ids: Sequence[str], + cluster_ids: t.Sequence[str], current_user: JWTUser = Depends(auth.get_current_user), ) -> None: """ @@ -1765,13 +2104,13 @@ def get_st_storage( path="/studies/{uuid}/areas/{area_id}/storages", tags=[APITag.study_data], summary="Get the list of short-term storage properties", - response_model=Sequence[STStorageOutput], + response_model=t.Sequence[STStorageOutput], ) def get_st_storages( uuid: str, area_id: str, current_user: JWTUser = Depends(auth.get_current_user), - ) -> Sequence[STStorageOutput]: + ) -> t.Sequence[STStorageOutput]: """ Retrieve the short-term storages by given uuid and area ID of a study. @@ -2015,7 +2354,7 @@ def update_st_storage( def delete_st_storages( uuid: str, area_id: str, - storage_ids: Sequence[str], + storage_ids: t.Sequence[str], current_user: JWTUser = Depends(auth.get_current_user), ) -> None: """ @@ -2047,9 +2386,9 @@ def duplicate_cluster( area_id: str, cluster_type: ClusterType, source_cluster_id: str, - new_cluster_name: str = Query(..., alias="newName", title="New Cluster Name"), # type: ignore + new_cluster_name: str = Query(..., alias="newName", title="New Cluster Name"), current_user: JWTUser = Depends(auth.get_current_user), - ) -> Union[STStorageOutput, ThermalClusterOutput, RenewableClusterOutput]: + ) -> t.Union[STStorageOutput, ThermalClusterOutput, RenewableClusterOutput]: logger.info( f"Duplicates {cluster_type.value} {source_cluster_id} of {area_id} for study {uuid}", extra={"user": current_user.id}, @@ -2057,7 +2396,7 @@ def duplicate_cluster( params = RequestParameters(user=current_user) study = study_service.check_study_access(uuid, StudyPermissionType.WRITE, params) - manager: Union[STStorageManager, RenewableManager, ThermalManager] + manager: t.Union[STStorageManager, RenewableManager, ThermalManager] if cluster_type == ClusterType.ST_STORAGES: manager = STStorageManager(study_service.storage_service) elif cluster_type == ClusterType.RENEWABLES: diff --git a/antarest/tools/lib.py b/antarest/tools/lib.py index c3c5db9dff..60e3215f5b 100644 --- a/antarest/tools/lib.py +++ b/antarest/tools/lib.py @@ -94,8 +94,6 @@ def apply_commands( res = self.session.post(self.build_url("/v1/matrix"), json=matrix_data) res.raise_for_status() matrix_id = res.json() - # file_name = matrix_file.with_suffix("").name - # assert matrix_id == file_name, f"{matrix_id} != {file_name}" matrix_dataset.append(matrix_id) # TODO could create a dataset from theses matrices using "variant_" as name @@ -117,10 +115,14 @@ def apply_commands( res.raise_for_status() stopwatch.log_elapsed(lambda x: logger.info(f"Generation done in {x}s")) - task_result = TaskDTO.parse_obj(res.json()) - assert task_result.result is not None + task_result = TaskDTO(**res.json()) - return GenerationResultInfoDTO.parse_raw(task_result.result.return_value or "") + if task_result.result is None or task_result.result.return_value is None: # pragma: no cover + # This should not happen, but if it does, we return a failed result + return GenerationResultInfoDTO(success=False, details=[]) + + info = json.loads(task_result.result.return_value) + return GenerationResultInfoDTO(**info) def build_url(self, url: str) -> str: return url if self.host is None else f"{self.host.strip('/')}/{url.strip('/')}" @@ -164,15 +166,15 @@ def apply_commands(self, commands: List[CommandDTO], matrices_dir: Path) -> Gene ) command_objs: List[List[ICommand]] = [] - logger.info("Parsing command objects") + logger.info("Parsing command objects...") command_objs.extend(command_factory.to_command(command_block) for command_block in commands) stopwatch.log_elapsed(lambda x: logger.info(f"Command objects parsed in {x}s")) result = generator.generate(command_objs, self.output_path, delete_on_failure=False) if result.success: # sourcery skip: extract-method - logger.info("Building new study tree") + logger.info("Building new study tree...") study = study_factory.create_from_fs(self.output_path, study_id="", use_cache=False) - logger.info("Denormalizing study") + logger.info("Denormalize study...") stopwatch.reset_current() study.tree.denormalize() stopwatch.log_elapsed(lambda x: logger.info(f"Denormalized done in {x}s")) @@ -323,7 +325,7 @@ def parse_commands(file: Path) -> List[CommandDTO]: json_commands = json.load(fh) stopwatch.log_elapsed(lambda x: logger.info(f"Script file read in {x}s")) - commands: List[CommandDTO] = [CommandDTO.parse_obj(command) for command in json_commands] + commands: List[CommandDTO] = [CommandDTO(**command) for command in json_commands] stopwatch.log_elapsed(lambda x: logger.info(f"Script commands parsed in {x}s")) return commands diff --git a/antarest/utils.py b/antarest/utils.py index 39ea094168..1f61717ada 100644 --- a/antarest/utils.py +++ b/antarest/utils.py @@ -101,9 +101,7 @@ def init_db_engine( return engine -def create_event_bus( - application: Optional[FastAPI], config: Config -) -> Tuple[IEventBus, Optional[redis.Redis]]: # type: ignore +def create_event_bus(application: Optional[FastAPI], config: Config) -> Tuple[IEventBus, Optional[redis.Redis]]: # type: ignore redis_client = new_redis_instance(config.redis) if config.redis is not None else None return ( build_eventbus(application, config, True, redis_client), diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 0000000000..080384a0a6 --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,10 @@ +import { RuleConfigSeverity } from "@commitlint/types"; + +// Config used by 'commitlint' GitHub action. +export default { + extends: ["@commitlint/config-conventional"], + // Rules: https://commitlint.js.org/reference/rules.html + rules: { + "header-max-length": [RuleConfigSeverity.Error, "always", 150], + }, +}; diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 3ab8134941..8b4933a3eb 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,36 @@ Antares Web Changelog ===================== +v2.17 (2024-05-15) +------------------ + +Support for evolutions relating to studies in versions 8.7: +- Scenarized RHS for binding constraints, +- Thermal cluster new properties (cost generation mode, efficiency, variable OM cost) + +Support for evolutions relating to studies in versions 8.8: +- Short-term storage¶: add `enabled` property +- Experimental "MILP" mode (using launcher options) + +### Features + +* **bc:** add endpoint for multiple terms edition [`#2020`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2020) +* **table-mode:** add missing properties for v8.6 and 8.7 [`#1643`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/1643) +* **ui-table-mode:** translate table types in add/edit modal + + +### Bug Fixes + +* **bc:** handle undefined v8.3 fields [`#2026`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2026) +* **table-mode:** hide `adequacy_patch_mode` column from table-mode before v8.3 [`#2022`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2022) +* **ui-common:** allow only import of TSV file in `MatrixInput` [`#2027`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2027) +* **ui-settings:** prevent false duplicates on group form updates [`#1998`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/1998) +* **ui-table-mode:** reset 'column' field when 'type' field change in create/update modal +* **ui-table-mode:** unable to edit tables with old types +* **ui-table-mode:** add missing "ST Storage" in Table Mode template [`#2016`](https://github.com/AntaresSimulatorTeam/AntaREST/pull/2016) +* **download**: improve performance of Excel file download + + v2.16.8 (2024-04-19) -------------------- diff --git a/docs/assets/media/user-guide/study/areas/05-hydro.min-generation.series.png b/docs/assets/media/user-guide/study/areas/05-hydro.min-generation.series.png new file mode 100644 index 0000000000..23372726ab Binary files /dev/null and b/docs/assets/media/user-guide/study/areas/05-hydro.min-generation.series.png differ diff --git a/docs/user-guide/study/areas/05-hydro.md b/docs/user-guide/study/areas/05-hydro.md index 40a02d4eca..c2a535bb2c 100644 --- a/docs/user-guide/study/areas/05-hydro.md +++ b/docs/user-guide/study/areas/05-hydro.md @@ -71,3 +71,9 @@ This tab allows you to configure the hydro storage time series of the hydraulic ## Run of River This tab allows you to configure the run of river time series of the hydraulic generators. + +## Minimum Generation + +The "Min Gen." tab is dedicated to configuring the minimum generation levels of the hydraulic generators. This tab presents a time series that represents the minimum hourly production for one or more Monte-Carlo years. + +![05-hydro.min-generation.series.png](../../../assets/media/user-guide/study/areas/05-hydro.min-generation.series.png) \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..e21a23c548 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1449 @@ +{ + "name": "AntaREST", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": { + "@commitlint/cli": "^19.2.1", + "@commitlint/config-conventional": "^19.1.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@commitlint/cli": { + "version": "19.2.1", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-19.2.1.tgz", + "integrity": "sha512-cbkYUJsLqRomccNxvoJTyv5yn0bSy05BBizVyIcLACkRbVUqYorC351Diw/XFSWC/GtpwiwT2eOvQgFZa374bg==", + "dev": true, + "dependencies": { + "@commitlint/format": "^19.0.3", + "@commitlint/lint": "^19.1.0", + "@commitlint/load": "^19.2.0", + "@commitlint/read": "^19.2.1", + "@commitlint/types": "^19.0.3", + "execa": "^8.0.1", + "yargs": "^17.0.0" + }, + "bin": { + "commitlint": "cli.js" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-conventional": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-19.1.0.tgz", + "integrity": "sha512-KIKD2xrp6Uuk+dcZVj3++MlzIr/Su6zLE8crEDQCZNvWHNQSeeGbzOlNtsR32TUy6H3JbP7nWgduAHCaiGQ6EA==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.0.3", + "conventional-changelog-conventionalcommits": "^7.0.2" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-validator": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-19.0.3.tgz", + "integrity": "sha512-2D3r4PKjoo59zBc2auodrSCaUnCSALCx54yveOFwwP/i2kfEAQrygwOleFWswLqK0UL/F9r07MFi5ev2ohyM4Q==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.0.3", + "ajv": "^8.11.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/ensure": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-19.0.3.tgz", + "integrity": "sha512-SZEpa/VvBLoT+EFZVb91YWbmaZ/9rPH3ESrINOl0HD2kMYsjvl0tF7nMHh0EpTcv4+gTtZBAe1y/SS6/OhfZzQ==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.0.3", + "lodash.camelcase": "^4.3.0", + "lodash.kebabcase": "^4.1.1", + "lodash.snakecase": "^4.1.1", + "lodash.startcase": "^4.4.0", + "lodash.upperfirst": "^4.3.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/execute-rule": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-19.0.0.tgz", + "integrity": "sha512-mtsdpY1qyWgAO/iOK0L6gSGeR7GFcdW7tIjcNFxcWkfLDF5qVbPHKuGATFqRMsxcO8OUKNj0+3WOHB7EHm4Jdw==", + "dev": true, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/format": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-19.0.3.tgz", + "integrity": "sha512-QjjyGyoiVWzx1f5xOteKHNLFyhyweVifMgopozSgx1fGNrGV8+wp7k6n1t6StHdJ6maQJ+UUtO2TcEiBFRyR6Q==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.0.3", + "chalk": "^5.3.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/is-ignored": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-19.0.3.tgz", + "integrity": "sha512-MqDrxJaRSVSzCbPsV6iOKG/Lt52Y+PVwFVexqImmYYFhe51iVJjK2hRhOG2jUAGiUHk4jpdFr0cZPzcBkSzXDQ==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.0.3", + "semver": "^7.6.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/lint": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-19.1.0.tgz", + "integrity": "sha512-ESjaBmL/9cxm+eePyEr6SFlBUIYlYpI80n+Ltm7IA3MAcrmiP05UMhJdAD66sO8jvo8O4xdGn/1Mt2G5VzfZKw==", + "dev": true, + "dependencies": { + "@commitlint/is-ignored": "^19.0.3", + "@commitlint/parse": "^19.0.3", + "@commitlint/rules": "^19.0.3", + "@commitlint/types": "^19.0.3" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/load": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-19.2.0.tgz", + "integrity": "sha512-XvxxLJTKqZojCxaBQ7u92qQLFMMZc4+p9qrIq/9kJDy8DOrEa7P1yx7Tjdc2u2JxIalqT4KOGraVgCE7eCYJyQ==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^19.0.3", + "@commitlint/execute-rule": "^19.0.0", + "@commitlint/resolve-extends": "^19.1.0", + "@commitlint/types": "^19.0.3", + "chalk": "^5.3.0", + "cosmiconfig": "^9.0.0", + "cosmiconfig-typescript-loader": "^5.0.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "lodash.uniq": "^4.5.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/message": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-19.0.0.tgz", + "integrity": "sha512-c9czf6lU+9oF9gVVa2lmKaOARJvt4soRsVmbR7Njwp9FpbBgste5i7l/2l5o8MmbwGh4yE1snfnsy2qyA2r/Fw==", + "dev": true, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/parse": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-19.0.3.tgz", + "integrity": "sha512-Il+tNyOb8VDxN3P6XoBBwWJtKKGzHlitEuXA5BP6ir/3loWlsSqDr5aecl6hZcC/spjq4pHqNh0qPlfeWu38QA==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.0.3", + "conventional-changelog-angular": "^7.0.0", + "conventional-commits-parser": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/read": { + "version": "19.2.1", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-19.2.1.tgz", + "integrity": "sha512-qETc4+PL0EUv7Q36lJbPG+NJiBOGg7SSC7B5BsPWOmei+Dyif80ErfWQ0qXoW9oCh7GTpTNRoaVhiI8RbhuaNw==", + "dev": true, + "dependencies": { + "@commitlint/top-level": "^19.0.0", + "@commitlint/types": "^19.0.3", + "execa": "^8.0.1", + "git-raw-commits": "^4.0.0", + "minimist": "^1.2.8" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/resolve-extends": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-19.1.0.tgz", + "integrity": "sha512-z2riI+8G3CET5CPgXJPlzftH+RiWYLMYv4C9tSLdLXdr6pBNimSKukYP9MS27ejmscqCTVA4almdLh0ODD2KYg==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^19.0.3", + "@commitlint/types": "^19.0.3", + "global-directory": "^4.0.1", + "import-meta-resolve": "^4.0.0", + "lodash.mergewith": "^4.6.2", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/rules": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-19.0.3.tgz", + "integrity": "sha512-TspKb9VB6svklxNCKKwxhELn7qhtY1rFF8ls58DcFd0F97XoG07xugPjjbVnLqmMkRjZDbDIwBKt9bddOfLaPw==", + "dev": true, + "dependencies": { + "@commitlint/ensure": "^19.0.3", + "@commitlint/message": "^19.0.0", + "@commitlint/to-lines": "^19.0.0", + "@commitlint/types": "^19.0.3", + "execa": "^8.0.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/to-lines": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-19.0.0.tgz", + "integrity": "sha512-vkxWo+VQU5wFhiP9Ub9Sre0FYe019JxFikrALVoD5UGa8/t3yOJEpEhxC5xKiENKKhUkTpEItMTRAjHw2SCpZw==", + "dev": true, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/top-level": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-19.0.0.tgz", + "integrity": "sha512-KKjShd6u1aMGNkCkaX4aG1jOGdn7f8ZI8TR1VEuNqUOjWTOdcDSsmglinglJ18JTjuBX5I1PtjrhQCRcixRVFQ==", + "dev": true, + "dependencies": { + "find-up": "^7.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/types": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-19.0.3.tgz", + "integrity": "sha512-tpyc+7i6bPG9mvaBbtKUeghfyZSDgWquIDfMgqYtTbmZ9Y9VzEm2je9EYcQ0aoz5o7NvGS+rcDec93yO08MHYA==", + "dev": true, + "dependencies": { + "@types/conventional-commits-parser": "^5.0.0", + "chalk": "^5.3.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@types/conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.11.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", + "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", + "dev": true + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "node_modules/conventional-changelog-angular": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", + "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz", + "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", + "dev": true, + "dependencies": { + "is-text-path": "^2.0.0", + "JSONStream": "^1.3.5", + "meow": "^12.0.1", + "split2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.mjs" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig-typescript-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-5.0.0.tgz", + "integrity": "sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==", + "dev": true, + "dependencies": { + "jiti": "^1.19.1" + }, + "engines": { + "node": ">=v16" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=8.2", + "typescript": ">=4" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/dargs": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz", + "integrity": "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/find-up": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz", + "integrity": "sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==", + "dev": true, + "dependencies": { + "locate-path": "^7.2.0", + "path-exists": "^5.0.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-raw-commits": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz", + "integrity": "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==", + "dev": true, + "dependencies": { + "dargs": "^8.0.0", + "meow": "^12.0.1", + "split2": "^4.0.0" + }, + "bin": { + "git-raw-commits": "cli.mjs" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/global-directory": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", + "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", + "dev": true, + "dependencies": { + "ini": "4.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-meta-resolve": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz", + "integrity": "sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-text-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", + "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", + "dev": true, + "dependencies": { + "text-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jiti": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", + "dev": true + }, + "node_modules/lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", + "dev": true + }, + "node_modules/lodash.startcase": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", + "dev": true + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "dev": true + }, + "node_modules/lodash.upperfirst": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", + "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", + "dev": true, + "engines": { + "node": ">=16.10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true, + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/text-extensions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", + "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/typescript": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", + "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", + "dev": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000000..affe100a23 --- /dev/null +++ b/package.json @@ -0,0 +1,7 @@ +{ + "type": "module", + "devDependencies": { + "@commitlint/cli": "^19.2.1", + "@commitlint/config-conventional": "^19.1.0" + } +} diff --git a/requirements-test.txt b/requirements-test.txt index 10e44592a1..8e408b2677 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,4 +1,8 @@ -r requirements.txt checksumdir~=1.2.0 pytest~=6.2.5 -pytest-cov~=4.0.0 \ No newline at end of file +pytest-cov~=4.0.0 + +# In this version DataFrame conversion to Excel is done using 'xlsxwriter' library. +# But Excel files reading is done using 'openpyxl' library, during testing only. +openpyxl~=3.1.2 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index d022e77ea3..835af45e10 100644 --- a/requirements.txt +++ b/requirements.txt @@ -27,5 +27,7 @@ redis~=4.1.2 requests~=2.27.1 SQLAlchemy~=1.4.46 starlette~=0.17.1 +tables typing_extensions~=4.7.1 -uvicorn[standard]~=0.15.0 \ No newline at end of file +uvicorn[standard]~=0.15.0 +xlsxwriter~=3.2.0 diff --git a/resources/empty_study_870.zip b/resources/empty_study_870.zip new file mode 100644 index 0000000000..7838152994 Binary files /dev/null and b/resources/empty_study_870.zip differ diff --git a/resources/empty_study_880.zip b/resources/empty_study_880.zip new file mode 100644 index 0000000000..3667408c59 Binary files /dev/null and b/resources/empty_study_880.zip differ diff --git a/scripts/package_antares_web.sh b/scripts/package_antares_web.sh index 21008c15f8..8b1999cfb9 100755 --- a/scripts/package_antares_web.sh +++ b/scripts/package_antares_web.sh @@ -9,7 +9,7 @@ set -e ANTARES_SOLVER_VERSION="8.8" -ANTARES_SOLVER_FULL_VERSION="8.8.3" +ANTARES_SOLVER_FULL_VERSION="8.8.4" ANTARES_SOLVER_VERSION_INT="880" SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd -P) diff --git a/scripts/rollback.sh b/scripts/rollback.sh index bf92685dc4..974ca59422 100755 --- a/scripts/rollback.sh +++ b/scripts/rollback.sh @@ -12,5 +12,5 @@ CUR_DIR=$(cd "$(dirname "$0")" && pwd) BASE_DIR=$(dirname "$CUR_DIR") cd "$BASE_DIR" -alembic downgrade 1f5db5dfad80 +alembic downgrade fd73601a9075 cd - diff --git a/setup.py b/setup.py index ce3b1690ea..76e6c3becb 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ setup( name="AntaREST", - version="2.16.8", + version="2.17", description="Antares Server", long_description=Path("README.md").read_text(encoding="utf-8"), long_description_content_type="text/markdown", diff --git a/sonar-project.properties b/sonar-project.properties index ed0c9da1c1..56212f62f5 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -6,5 +6,5 @@ sonar.exclusions=antarest/gui.py,antarest/main.py sonar.python.coverage.reportPaths=coverage.xml sonar.python.version=3.8 sonar.javascript.lcov.reportPaths=webapp/coverage/lcov.info -sonar.projectVersion=2.16.8 +sonar.projectVersion=2.17 sonar.coverage.exclusions=antarest/gui.py,antarest/main.py,antarest/singleton_services.py,antarest/worker/archive_worker_service.py,webapp/**/* \ No newline at end of file diff --git a/tests/helpers.py b/tests/helpers.py index a9cfdb9ee8..0736eafd59 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -1,4 +1,5 @@ import time +import uuid from datetime import datetime, timedelta, timezone from functools import wraps from typing import Any, Callable, Dict, List, cast @@ -76,3 +77,26 @@ def auto_retry_assert(predicate: Callable[..., bool], timeout: int = 2, delay: f return time.sleep(delay) raise AssertionError() + + +class AnyUUID: + """Mock object to match any UUID.""" + + def __init__(self, as_string: bool = False): + self.as_string = as_string + + def __eq__(self, other: object) -> bool: + if isinstance(other, AnyUUID): + return True + if isinstance(other, str): + if self.as_string: + try: + uuid.UUID(other) + return True + except ValueError: + return False + return False + return isinstance(other, uuid.UUID) + + def __ne__(self, other: object) -> bool: + return not self.__eq__(other) diff --git a/tests/integration/assets/base_study.zip b/tests/integration/assets/base_study.zip index 8a79496138..3b282beb16 100644 Binary files a/tests/integration/assets/base_study.zip and b/tests/integration/assets/base_study.zip differ diff --git a/tests/integration/assets/variant_study.zip b/tests/integration/assets/variant_study.zip index e19151bb07..4526fc900f 100644 Binary files a/tests/integration/assets/variant_study.zip and b/tests/integration/assets/variant_study.zip differ diff --git a/tests/integration/raw_studies_blueprint/assets/aggregate_areas_raw_data/test-01.result.tsv b/tests/integration/raw_studies_blueprint/assets/aggregate_areas_raw_data/test-01.result.tsv new file mode 100644 index 0000000000..4455dcaf42 --- /dev/null +++ b/tests/integration/raw_studies_blueprint/assets/aggregate_areas_raw_data/test-01.result.tsv @@ -0,0 +1,2689 @@ +area mcYear timeId time OV. COST OP. COST MRG. PRICE CO2 EMIS. BALANCE ROW BAL. PSP MISC. NDG LOAD H. ROR WIND SOLAR NUCLEAR LIGNITE COAL GAS OIL MIX. FUEL MISC. DTG H. STOR H. PUMP H. LEV H. INFL H. OVFL H. VAL H. COST UNSP. ENRG SPIL. ENRG LOLD LOLP AVL DTG DTG MRG MAX MRG NP COST NODU +de 1 1 01/01 00:00 0.0 0.0 9.98 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +de 1 2 01/01 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +de 1 3 01/01 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +de 1 4 01/01 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +de 1 5 01/01 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +de 1 6 01/01 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +de 1 7 01/01 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +de 1 8 01/01 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +de 1 9 01/01 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +de 1 10 01/01 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +de 1 11 01/01 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +de 1 12 01/01 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +de 1 13 01/01 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +de 1 14 01/01 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +de 1 15 01/01 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +de 1 16 01/01 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +de 1 17 01/01 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +de 1 18 01/01 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +de 1 19 01/01 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +de 1 20 01/01 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +de 1 21 01/01 20:00 20000.0 20000.0 19.98 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +de 1 22 01/01 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +de 1 23 01/01 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +de 1 24 01/01 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +de 1 25 01/02 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +de 1 26 01/02 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +de 1 27 01/02 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +de 1 28 01/02 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +de 1 29 01/02 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +de 1 30 01/02 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +de 1 31 01/02 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +de 1 32 01/02 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +de 1 33 01/02 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +de 1 34 01/02 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +de 1 35 01/02 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +de 1 36 01/02 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +de 1 37 01/02 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +de 1 38 01/02 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +de 1 39 01/02 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +de 1 40 01/02 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +de 1 41 01/02 16:00 60000.0 60000.0 29.98 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +de 1 42 01/02 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +de 1 43 01/02 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +de 1 44 01/02 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +de 1 45 01/02 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +de 1 46 01/02 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +de 1 47 01/02 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +de 1 48 01/02 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +de 1 49 01/03 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +de 1 50 01/03 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +de 1 51 01/03 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +de 1 52 01/03 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +de 1 53 01/03 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +de 1 54 01/03 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +de 1 55 01/03 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +de 1 56 01/03 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +de 1 57 01/03 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +de 1 58 01/03 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +de 1 59 01/03 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +de 1 60 01/03 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +de 1 61 01/03 12:00 120000.0 120000.0 39.98 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +de 1 62 01/03 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +de 1 63 01/03 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +de 1 64 01/03 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +de 1 65 01/03 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +de 1 66 01/03 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +de 1 67 01/03 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +de 1 68 01/03 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +de 1 69 01/03 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +de 1 70 01/03 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +de 1 71 01/03 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +de 1 72 01/03 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +de 1 73 01/04 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +de 1 74 01/04 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +de 1 75 01/04 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +de 1 76 01/04 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +de 1 77 01/04 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +de 1 78 01/04 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +de 1 79 01/04 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +de 1 80 01/04 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +de 1 81 01/04 08:00 200000.0 200000.0 49.98 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +de 1 82 01/04 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +de 1 83 01/04 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +de 1 84 01/04 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +de 1 85 01/04 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +de 1 86 01/04 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +de 1 87 01/04 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +de 1 88 01/04 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +de 1 89 01/04 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +de 1 90 01/04 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +de 1 91 01/04 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +de 1 92 01/04 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +de 1 93 01/04 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +de 1 94 01/04 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +de 1 95 01/04 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +de 1 96 01/04 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +de 1 97 01/05 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +de 1 98 01/05 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +de 1 99 01/05 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +de 1 100 01/05 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +de 1 101 01/05 04:00 300000.0 300000.0 59.98 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +de 1 102 01/05 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +de 1 103 01/05 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +de 1 104 01/05 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +de 1 105 01/05 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +de 1 106 01/05 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +de 1 107 01/05 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +de 1 108 01/05 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +de 1 109 01/05 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +de 1 110 01/05 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +de 1 111 01/05 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +de 1 112 01/05 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +de 1 113 01/05 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +de 1 114 01/05 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +de 1 115 01/05 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +de 1 116 01/05 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +de 1 117 01/05 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +de 1 118 01/05 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +de 1 119 01/05 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +de 1 120 01/05 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +de 1 121 01/06 00:00 420000.0 420000.0 69.98 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +de 1 122 01/06 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +de 1 123 01/06 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +de 1 124 01/06 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +de 1 125 01/06 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +de 1 126 01/06 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +de 1 127 01/06 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +de 1 128 01/06 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +de 1 129 01/06 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +de 1 130 01/06 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +de 1 131 01/06 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +de 1 132 01/06 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +de 1 133 01/06 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +de 1 134 01/06 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +de 1 135 01/06 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +de 1 136 01/06 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +de 1 137 01/06 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +de 1 138 01/06 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +de 1 139 01/06 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +de 1 140 01/06 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +de 1 141 01/06 20:00 560000.0 560000.0 79.98 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +de 1 142 01/06 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +de 1 143 01/06 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +de 1 144 01/06 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +de 1 145 01/07 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +de 1 146 01/07 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +de 1 147 01/07 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +de 1 148 01/07 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +de 1 149 01/07 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +de 1 150 01/07 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +de 1 151 01/07 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +de 1 152 01/07 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +de 1 153 01/07 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +de 1 154 01/07 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +de 1 155 01/07 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +de 1 156 01/07 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +de 1 157 01/07 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +de 1 158 01/07 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +de 1 159 01/07 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +de 1 160 01/07 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +de 1 161 01/07 16:00 720000.0 720000.0 89.98 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +de 1 162 01/07 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +de 1 163 01/07 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +de 1 164 01/07 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +de 1 165 01/07 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +de 1 166 01/07 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +de 1 167 01/07 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +de 1 168 01/07 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 +de 1 169 01/08 00:00 0.0 0.0 9.98 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +de 1 170 01/08 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +de 1 171 01/08 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +de 1 172 01/08 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +de 1 173 01/08 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +de 1 174 01/08 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +de 1 175 01/08 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +de 1 176 01/08 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +de 1 177 01/08 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +de 1 178 01/08 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +de 1 179 01/08 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +de 1 180 01/08 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +de 1 181 01/08 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +de 1 182 01/08 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +de 1 183 01/08 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +de 1 184 01/08 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +de 1 185 01/08 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +de 1 186 01/08 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +de 1 187 01/08 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +de 1 188 01/08 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +de 1 189 01/08 20:00 20000.0 20000.0 19.98 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +de 1 190 01/08 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +de 1 191 01/08 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +de 1 192 01/08 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +de 1 193 01/09 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +de 1 194 01/09 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +de 1 195 01/09 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +de 1 196 01/09 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +de 1 197 01/09 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +de 1 198 01/09 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +de 1 199 01/09 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +de 1 200 01/09 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +de 1 201 01/09 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +de 1 202 01/09 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +de 1 203 01/09 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +de 1 204 01/09 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +de 1 205 01/09 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +de 1 206 01/09 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +de 1 207 01/09 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +de 1 208 01/09 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +de 1 209 01/09 16:00 60000.0 60000.0 29.98 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +de 1 210 01/09 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +de 1 211 01/09 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +de 1 212 01/09 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +de 1 213 01/09 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +de 1 214 01/09 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +de 1 215 01/09 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +de 1 216 01/09 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +de 1 217 01/10 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +de 1 218 01/10 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +de 1 219 01/10 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +de 1 220 01/10 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +de 1 221 01/10 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +de 1 222 01/10 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +de 1 223 01/10 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +de 1 224 01/10 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +de 1 225 01/10 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +de 1 226 01/10 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +de 1 227 01/10 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +de 1 228 01/10 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +de 1 229 01/10 12:00 120000.0 120000.0 39.98 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +de 1 230 01/10 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +de 1 231 01/10 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +de 1 232 01/10 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +de 1 233 01/10 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +de 1 234 01/10 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +de 1 235 01/10 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +de 1 236 01/10 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +de 1 237 01/10 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +de 1 238 01/10 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +de 1 239 01/10 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +de 1 240 01/10 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +de 1 241 01/11 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +de 1 242 01/11 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +de 1 243 01/11 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +de 1 244 01/11 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +de 1 245 01/11 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +de 1 246 01/11 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +de 1 247 01/11 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +de 1 248 01/11 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +de 1 249 01/11 08:00 200000.0 200000.0 49.98 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +de 1 250 01/11 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +de 1 251 01/11 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +de 1 252 01/11 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +de 1 253 01/11 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +de 1 254 01/11 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +de 1 255 01/11 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +de 1 256 01/11 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +de 1 257 01/11 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +de 1 258 01/11 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +de 1 259 01/11 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +de 1 260 01/11 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +de 1 261 01/11 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +de 1 262 01/11 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +de 1 263 01/11 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +de 1 264 01/11 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +de 1 265 01/12 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +de 1 266 01/12 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +de 1 267 01/12 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +de 1 268 01/12 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +de 1 269 01/12 04:00 300000.0 300000.0 59.98 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +de 1 270 01/12 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +de 1 271 01/12 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +de 1 272 01/12 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +de 1 273 01/12 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +de 1 274 01/12 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +de 1 275 01/12 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +de 1 276 01/12 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +de 1 277 01/12 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +de 1 278 01/12 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +de 1 279 01/12 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +de 1 280 01/12 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +de 1 281 01/12 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +de 1 282 01/12 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +de 1 283 01/12 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +de 1 284 01/12 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +de 1 285 01/12 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +de 1 286 01/12 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +de 1 287 01/12 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +de 1 288 01/12 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +de 1 289 01/13 00:00 420000.0 420000.0 69.98 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +de 1 290 01/13 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +de 1 291 01/13 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +de 1 292 01/13 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +de 1 293 01/13 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +de 1 294 01/13 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +de 1 295 01/13 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +de 1 296 01/13 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +de 1 297 01/13 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +de 1 298 01/13 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +de 1 299 01/13 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +de 1 300 01/13 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +de 1 301 01/13 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +de 1 302 01/13 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +de 1 303 01/13 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +de 1 304 01/13 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +de 1 305 01/13 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +de 1 306 01/13 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +de 1 307 01/13 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +de 1 308 01/13 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +de 1 309 01/13 20:00 560000.0 560000.0 79.98 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +de 1 310 01/13 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +de 1 311 01/13 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +de 1 312 01/13 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +de 1 313 01/14 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +de 1 314 01/14 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +de 1 315 01/14 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +de 1 316 01/14 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +de 1 317 01/14 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +de 1 318 01/14 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +de 1 319 01/14 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +de 1 320 01/14 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +de 1 321 01/14 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +de 1 322 01/14 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +de 1 323 01/14 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +de 1 324 01/14 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +de 1 325 01/14 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +de 1 326 01/14 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +de 1 327 01/14 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +de 1 328 01/14 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +de 1 329 01/14 16:00 720000.0 720000.0 89.98 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +de 1 330 01/14 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +de 1 331 01/14 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +de 1 332 01/14 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +de 1 333 01/14 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +de 1 334 01/14 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +de 1 335 01/14 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +de 1 336 01/14 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 +es 1 1 01/01 00:00 0.0 0.0 9.98 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +es 1 2 01/01 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +es 1 3 01/01 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +es 1 4 01/01 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +es 1 5 01/01 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +es 1 6 01/01 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +es 1 7 01/01 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +es 1 8 01/01 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +es 1 9 01/01 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +es 1 10 01/01 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +es 1 11 01/01 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +es 1 12 01/01 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +es 1 13 01/01 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +es 1 14 01/01 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +es 1 15 01/01 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +es 1 16 01/01 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +es 1 17 01/01 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +es 1 18 01/01 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +es 1 19 01/01 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +es 1 20 01/01 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +es 1 21 01/01 20:00 20000.0 20000.0 19.98 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +es 1 22 01/01 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +es 1 23 01/01 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +es 1 24 01/01 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +es 1 25 01/02 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +es 1 26 01/02 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +es 1 27 01/02 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +es 1 28 01/02 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +es 1 29 01/02 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +es 1 30 01/02 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +es 1 31 01/02 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +es 1 32 01/02 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +es 1 33 01/02 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +es 1 34 01/02 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +es 1 35 01/02 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +es 1 36 01/02 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +es 1 37 01/02 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +es 1 38 01/02 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +es 1 39 01/02 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +es 1 40 01/02 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +es 1 41 01/02 16:00 60000.0 60000.0 29.98 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +es 1 42 01/02 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +es 1 43 01/02 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +es 1 44 01/02 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +es 1 45 01/02 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +es 1 46 01/02 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +es 1 47 01/02 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +es 1 48 01/02 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +es 1 49 01/03 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +es 1 50 01/03 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +es 1 51 01/03 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +es 1 52 01/03 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +es 1 53 01/03 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +es 1 54 01/03 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +es 1 55 01/03 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +es 1 56 01/03 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +es 1 57 01/03 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +es 1 58 01/03 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +es 1 59 01/03 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +es 1 60 01/03 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +es 1 61 01/03 12:00 120000.0 120000.0 39.98 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +es 1 62 01/03 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +es 1 63 01/03 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +es 1 64 01/03 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +es 1 65 01/03 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +es 1 66 01/03 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +es 1 67 01/03 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +es 1 68 01/03 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +es 1 69 01/03 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +es 1 70 01/03 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +es 1 71 01/03 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +es 1 72 01/03 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +es 1 73 01/04 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +es 1 74 01/04 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +es 1 75 01/04 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +es 1 76 01/04 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +es 1 77 01/04 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +es 1 78 01/04 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +es 1 79 01/04 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +es 1 80 01/04 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +es 1 81 01/04 08:00 200000.0 200000.0 49.98 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +es 1 82 01/04 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +es 1 83 01/04 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +es 1 84 01/04 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +es 1 85 01/04 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +es 1 86 01/04 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +es 1 87 01/04 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +es 1 88 01/04 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +es 1 89 01/04 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +es 1 90 01/04 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +es 1 91 01/04 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +es 1 92 01/04 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +es 1 93 01/04 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +es 1 94 01/04 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +es 1 95 01/04 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +es 1 96 01/04 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +es 1 97 01/05 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +es 1 98 01/05 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +es 1 99 01/05 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +es 1 100 01/05 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +es 1 101 01/05 04:00 300000.0 300000.0 59.98 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +es 1 102 01/05 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +es 1 103 01/05 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +es 1 104 01/05 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +es 1 105 01/05 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +es 1 106 01/05 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +es 1 107 01/05 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +es 1 108 01/05 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +es 1 109 01/05 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +es 1 110 01/05 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +es 1 111 01/05 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +es 1 112 01/05 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +es 1 113 01/05 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +es 1 114 01/05 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +es 1 115 01/05 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +es 1 116 01/05 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +es 1 117 01/05 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +es 1 118 01/05 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +es 1 119 01/05 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +es 1 120 01/05 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +es 1 121 01/06 00:00 420000.0 420000.0 69.98 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +es 1 122 01/06 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +es 1 123 01/06 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +es 1 124 01/06 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +es 1 125 01/06 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +es 1 126 01/06 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +es 1 127 01/06 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +es 1 128 01/06 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +es 1 129 01/06 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +es 1 130 01/06 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +es 1 131 01/06 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +es 1 132 01/06 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +es 1 133 01/06 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +es 1 134 01/06 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +es 1 135 01/06 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +es 1 136 01/06 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +es 1 137 01/06 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +es 1 138 01/06 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +es 1 139 01/06 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +es 1 140 01/06 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +es 1 141 01/06 20:00 560000.0 560000.0 79.98 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +es 1 142 01/06 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +es 1 143 01/06 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +es 1 144 01/06 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +es 1 145 01/07 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +es 1 146 01/07 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +es 1 147 01/07 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +es 1 148 01/07 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +es 1 149 01/07 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +es 1 150 01/07 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +es 1 151 01/07 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +es 1 152 01/07 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +es 1 153 01/07 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +es 1 154 01/07 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +es 1 155 01/07 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +es 1 156 01/07 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +es 1 157 01/07 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +es 1 158 01/07 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +es 1 159 01/07 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +es 1 160 01/07 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +es 1 161 01/07 16:00 720000.0 720000.0 89.98 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +es 1 162 01/07 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +es 1 163 01/07 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +es 1 164 01/07 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +es 1 165 01/07 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +es 1 166 01/07 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +es 1 167 01/07 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +es 1 168 01/07 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 +es 1 169 01/08 00:00 0.0 0.0 9.98 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +es 1 170 01/08 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +es 1 171 01/08 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +es 1 172 01/08 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +es 1 173 01/08 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +es 1 174 01/08 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +es 1 175 01/08 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +es 1 176 01/08 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +es 1 177 01/08 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +es 1 178 01/08 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +es 1 179 01/08 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +es 1 180 01/08 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +es 1 181 01/08 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +es 1 182 01/08 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +es 1 183 01/08 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +es 1 184 01/08 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +es 1 185 01/08 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +es 1 186 01/08 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +es 1 187 01/08 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +es 1 188 01/08 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +es 1 189 01/08 20:00 20000.0 20000.0 19.98 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +es 1 190 01/08 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +es 1 191 01/08 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +es 1 192 01/08 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +es 1 193 01/09 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +es 1 194 01/09 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +es 1 195 01/09 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +es 1 196 01/09 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +es 1 197 01/09 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +es 1 198 01/09 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +es 1 199 01/09 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +es 1 200 01/09 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +es 1 201 01/09 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +es 1 202 01/09 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +es 1 203 01/09 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +es 1 204 01/09 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +es 1 205 01/09 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +es 1 206 01/09 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +es 1 207 01/09 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +es 1 208 01/09 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +es 1 209 01/09 16:00 60000.0 60000.0 29.98 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +es 1 210 01/09 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +es 1 211 01/09 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +es 1 212 01/09 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +es 1 213 01/09 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +es 1 214 01/09 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +es 1 215 01/09 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +es 1 216 01/09 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +es 1 217 01/10 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +es 1 218 01/10 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +es 1 219 01/10 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +es 1 220 01/10 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +es 1 221 01/10 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +es 1 222 01/10 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +es 1 223 01/10 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +es 1 224 01/10 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +es 1 225 01/10 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +es 1 226 01/10 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +es 1 227 01/10 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +es 1 228 01/10 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +es 1 229 01/10 12:00 120000.0 120000.0 39.98 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +es 1 230 01/10 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +es 1 231 01/10 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +es 1 232 01/10 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +es 1 233 01/10 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +es 1 234 01/10 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +es 1 235 01/10 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +es 1 236 01/10 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +es 1 237 01/10 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +es 1 238 01/10 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +es 1 239 01/10 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +es 1 240 01/10 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +es 1 241 01/11 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +es 1 242 01/11 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +es 1 243 01/11 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +es 1 244 01/11 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +es 1 245 01/11 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +es 1 246 01/11 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +es 1 247 01/11 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +es 1 248 01/11 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +es 1 249 01/11 08:00 200000.0 200000.0 49.98 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +es 1 250 01/11 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +es 1 251 01/11 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +es 1 252 01/11 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +es 1 253 01/11 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +es 1 254 01/11 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +es 1 255 01/11 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +es 1 256 01/11 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +es 1 257 01/11 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +es 1 258 01/11 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +es 1 259 01/11 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +es 1 260 01/11 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +es 1 261 01/11 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +es 1 262 01/11 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +es 1 263 01/11 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +es 1 264 01/11 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +es 1 265 01/12 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +es 1 266 01/12 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +es 1 267 01/12 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +es 1 268 01/12 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +es 1 269 01/12 04:00 300000.0 300000.0 59.98 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +es 1 270 01/12 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +es 1 271 01/12 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +es 1 272 01/12 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +es 1 273 01/12 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +es 1 274 01/12 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +es 1 275 01/12 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +es 1 276 01/12 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +es 1 277 01/12 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +es 1 278 01/12 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +es 1 279 01/12 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +es 1 280 01/12 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +es 1 281 01/12 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +es 1 282 01/12 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +es 1 283 01/12 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +es 1 284 01/12 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +es 1 285 01/12 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +es 1 286 01/12 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +es 1 287 01/12 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +es 1 288 01/12 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +es 1 289 01/13 00:00 420000.0 420000.0 69.98 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +es 1 290 01/13 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +es 1 291 01/13 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +es 1 292 01/13 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +es 1 293 01/13 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +es 1 294 01/13 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +es 1 295 01/13 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +es 1 296 01/13 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +es 1 297 01/13 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +es 1 298 01/13 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +es 1 299 01/13 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +es 1 300 01/13 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +es 1 301 01/13 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +es 1 302 01/13 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +es 1 303 01/13 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +es 1 304 01/13 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +es 1 305 01/13 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +es 1 306 01/13 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +es 1 307 01/13 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +es 1 308 01/13 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +es 1 309 01/13 20:00 560000.0 560000.0 79.98 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +es 1 310 01/13 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +es 1 311 01/13 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +es 1 312 01/13 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +es 1 313 01/14 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +es 1 314 01/14 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +es 1 315 01/14 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +es 1 316 01/14 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +es 1 317 01/14 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +es 1 318 01/14 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +es 1 319 01/14 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +es 1 320 01/14 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +es 1 321 01/14 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +es 1 322 01/14 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +es 1 323 01/14 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +es 1 324 01/14 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +es 1 325 01/14 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +es 1 326 01/14 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +es 1 327 01/14 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +es 1 328 01/14 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +es 1 329 01/14 16:00 720000.0 720000.0 89.98 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +es 1 330 01/14 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +es 1 331 01/14 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +es 1 332 01/14 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +es 1 333 01/14 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +es 1 334 01/14 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +es 1 335 01/14 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +es 1 336 01/14 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 +fr 1 1 01/01 00:00 0.0 0.0 9.99 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +fr 1 2 01/01 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +fr 1 3 01/01 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +fr 1 4 01/01 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +fr 1 5 01/01 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +fr 1 6 01/01 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +fr 1 7 01/01 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +fr 1 8 01/01 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +fr 1 9 01/01 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +fr 1 10 01/01 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +fr 1 11 01/01 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +fr 1 12 01/01 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +fr 1 13 01/01 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +fr 1 14 01/01 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +fr 1 15 01/01 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +fr 1 16 01/01 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +fr 1 17 01/01 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +fr 1 18 01/01 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +fr 1 19 01/01 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +fr 1 20 01/01 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +fr 1 21 01/01 20:00 20000.0 20000.0 19.99 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +fr 1 22 01/01 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +fr 1 23 01/01 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +fr 1 24 01/01 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +fr 1 25 01/02 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +fr 1 26 01/02 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +fr 1 27 01/02 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +fr 1 28 01/02 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +fr 1 29 01/02 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +fr 1 30 01/02 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +fr 1 31 01/02 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +fr 1 32 01/02 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +fr 1 33 01/02 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +fr 1 34 01/02 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +fr 1 35 01/02 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +fr 1 36 01/02 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +fr 1 37 01/02 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +fr 1 38 01/02 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +fr 1 39 01/02 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +fr 1 40 01/02 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +fr 1 41 01/02 16:00 60000.0 60000.0 29.99 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +fr 1 42 01/02 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +fr 1 43 01/02 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +fr 1 44 01/02 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +fr 1 45 01/02 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +fr 1 46 01/02 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +fr 1 47 01/02 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +fr 1 48 01/02 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +fr 1 49 01/03 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +fr 1 50 01/03 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +fr 1 51 01/03 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +fr 1 52 01/03 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +fr 1 53 01/03 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +fr 1 54 01/03 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +fr 1 55 01/03 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +fr 1 56 01/03 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +fr 1 57 01/03 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +fr 1 58 01/03 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +fr 1 59 01/03 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +fr 1 60 01/03 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +fr 1 61 01/03 12:00 120000.0 120000.0 39.99 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +fr 1 62 01/03 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +fr 1 63 01/03 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +fr 1 64 01/03 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +fr 1 65 01/03 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +fr 1 66 01/03 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +fr 1 67 01/03 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +fr 1 68 01/03 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +fr 1 69 01/03 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +fr 1 70 01/03 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +fr 1 71 01/03 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +fr 1 72 01/03 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +fr 1 73 01/04 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +fr 1 74 01/04 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +fr 1 75 01/04 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +fr 1 76 01/04 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +fr 1 77 01/04 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +fr 1 78 01/04 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +fr 1 79 01/04 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +fr 1 80 01/04 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +fr 1 81 01/04 08:00 200000.0 200000.0 49.99 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +fr 1 82 01/04 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +fr 1 83 01/04 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +fr 1 84 01/04 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +fr 1 85 01/04 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +fr 1 86 01/04 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +fr 1 87 01/04 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +fr 1 88 01/04 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +fr 1 89 01/04 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +fr 1 90 01/04 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +fr 1 91 01/04 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +fr 1 92 01/04 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +fr 1 93 01/04 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +fr 1 94 01/04 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +fr 1 95 01/04 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +fr 1 96 01/04 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +fr 1 97 01/05 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +fr 1 98 01/05 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +fr 1 99 01/05 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +fr 1 100 01/05 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +fr 1 101 01/05 04:00 300000.0 300000.0 59.99 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +fr 1 102 01/05 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +fr 1 103 01/05 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +fr 1 104 01/05 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +fr 1 105 01/05 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +fr 1 106 01/05 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +fr 1 107 01/05 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +fr 1 108 01/05 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +fr 1 109 01/05 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +fr 1 110 01/05 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +fr 1 111 01/05 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +fr 1 112 01/05 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +fr 1 113 01/05 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +fr 1 114 01/05 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +fr 1 115 01/05 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +fr 1 116 01/05 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +fr 1 117 01/05 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +fr 1 118 01/05 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +fr 1 119 01/05 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +fr 1 120 01/05 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +fr 1 121 01/06 00:00 420000.0 420000.0 69.99 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +fr 1 122 01/06 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +fr 1 123 01/06 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +fr 1 124 01/06 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +fr 1 125 01/06 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +fr 1 126 01/06 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +fr 1 127 01/06 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +fr 1 128 01/06 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +fr 1 129 01/06 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +fr 1 130 01/06 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +fr 1 131 01/06 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +fr 1 132 01/06 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +fr 1 133 01/06 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +fr 1 134 01/06 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +fr 1 135 01/06 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +fr 1 136 01/06 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +fr 1 137 01/06 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +fr 1 138 01/06 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +fr 1 139 01/06 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +fr 1 140 01/06 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +fr 1 141 01/06 20:00 560000.0 560000.0 79.99 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +fr 1 142 01/06 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +fr 1 143 01/06 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +fr 1 144 01/06 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +fr 1 145 01/07 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +fr 1 146 01/07 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +fr 1 147 01/07 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +fr 1 148 01/07 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +fr 1 149 01/07 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +fr 1 150 01/07 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +fr 1 151 01/07 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +fr 1 152 01/07 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +fr 1 153 01/07 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +fr 1 154 01/07 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +fr 1 155 01/07 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +fr 1 156 01/07 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +fr 1 157 01/07 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +fr 1 158 01/07 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +fr 1 159 01/07 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +fr 1 160 01/07 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +fr 1 161 01/07 16:00 720000.0 720000.0 89.99 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +fr 1 162 01/07 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +fr 1 163 01/07 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +fr 1 164 01/07 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +fr 1 165 01/07 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +fr 1 166 01/07 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +fr 1 167 01/07 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +fr 1 168 01/07 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 +fr 1 169 01/08 00:00 0.0 0.0 9.99 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +fr 1 170 01/08 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +fr 1 171 01/08 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +fr 1 172 01/08 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +fr 1 173 01/08 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +fr 1 174 01/08 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +fr 1 175 01/08 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +fr 1 176 01/08 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +fr 1 177 01/08 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +fr 1 178 01/08 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +fr 1 179 01/08 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +fr 1 180 01/08 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +fr 1 181 01/08 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +fr 1 182 01/08 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +fr 1 183 01/08 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +fr 1 184 01/08 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +fr 1 185 01/08 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +fr 1 186 01/08 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +fr 1 187 01/08 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +fr 1 188 01/08 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +fr 1 189 01/08 20:00 20000.0 20000.0 19.99 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +fr 1 190 01/08 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +fr 1 191 01/08 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +fr 1 192 01/08 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +fr 1 193 01/09 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +fr 1 194 01/09 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +fr 1 195 01/09 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +fr 1 196 01/09 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +fr 1 197 01/09 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +fr 1 198 01/09 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +fr 1 199 01/09 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +fr 1 200 01/09 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +fr 1 201 01/09 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +fr 1 202 01/09 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +fr 1 203 01/09 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +fr 1 204 01/09 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +fr 1 205 01/09 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +fr 1 206 01/09 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +fr 1 207 01/09 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +fr 1 208 01/09 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +fr 1 209 01/09 16:00 60000.0 60000.0 29.99 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +fr 1 210 01/09 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +fr 1 211 01/09 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +fr 1 212 01/09 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +fr 1 213 01/09 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +fr 1 214 01/09 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +fr 1 215 01/09 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +fr 1 216 01/09 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +fr 1 217 01/10 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +fr 1 218 01/10 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +fr 1 219 01/10 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +fr 1 220 01/10 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +fr 1 221 01/10 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +fr 1 222 01/10 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +fr 1 223 01/10 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +fr 1 224 01/10 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +fr 1 225 01/10 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +fr 1 226 01/10 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +fr 1 227 01/10 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +fr 1 228 01/10 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +fr 1 229 01/10 12:00 120000.0 120000.0 39.99 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +fr 1 230 01/10 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +fr 1 231 01/10 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +fr 1 232 01/10 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +fr 1 233 01/10 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +fr 1 234 01/10 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +fr 1 235 01/10 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +fr 1 236 01/10 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +fr 1 237 01/10 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +fr 1 238 01/10 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +fr 1 239 01/10 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +fr 1 240 01/10 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +fr 1 241 01/11 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +fr 1 242 01/11 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +fr 1 243 01/11 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +fr 1 244 01/11 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +fr 1 245 01/11 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +fr 1 246 01/11 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +fr 1 247 01/11 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +fr 1 248 01/11 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +fr 1 249 01/11 08:00 200000.0 200000.0 49.99 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +fr 1 250 01/11 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +fr 1 251 01/11 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +fr 1 252 01/11 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +fr 1 253 01/11 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +fr 1 254 01/11 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +fr 1 255 01/11 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +fr 1 256 01/11 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +fr 1 257 01/11 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +fr 1 258 01/11 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +fr 1 259 01/11 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +fr 1 260 01/11 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +fr 1 261 01/11 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +fr 1 262 01/11 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +fr 1 263 01/11 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +fr 1 264 01/11 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +fr 1 265 01/12 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +fr 1 266 01/12 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +fr 1 267 01/12 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +fr 1 268 01/12 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +fr 1 269 01/12 04:00 300000.0 300000.0 59.99 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +fr 1 270 01/12 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +fr 1 271 01/12 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +fr 1 272 01/12 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +fr 1 273 01/12 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +fr 1 274 01/12 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +fr 1 275 01/12 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +fr 1 276 01/12 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +fr 1 277 01/12 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +fr 1 278 01/12 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +fr 1 279 01/12 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +fr 1 280 01/12 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +fr 1 281 01/12 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +fr 1 282 01/12 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +fr 1 283 01/12 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +fr 1 284 01/12 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +fr 1 285 01/12 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +fr 1 286 01/12 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +fr 1 287 01/12 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +fr 1 288 01/12 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +fr 1 289 01/13 00:00 420000.0 420000.0 69.99 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +fr 1 290 01/13 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +fr 1 291 01/13 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +fr 1 292 01/13 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +fr 1 293 01/13 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +fr 1 294 01/13 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +fr 1 295 01/13 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +fr 1 296 01/13 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +fr 1 297 01/13 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +fr 1 298 01/13 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +fr 1 299 01/13 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +fr 1 300 01/13 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +fr 1 301 01/13 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +fr 1 302 01/13 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +fr 1 303 01/13 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +fr 1 304 01/13 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +fr 1 305 01/13 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +fr 1 306 01/13 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +fr 1 307 01/13 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +fr 1 308 01/13 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +fr 1 309 01/13 20:00 560000.0 560000.0 79.99 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +fr 1 310 01/13 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +fr 1 311 01/13 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +fr 1 312 01/13 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +fr 1 313 01/14 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +fr 1 314 01/14 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +fr 1 315 01/14 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +fr 1 316 01/14 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +fr 1 317 01/14 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +fr 1 318 01/14 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +fr 1 319 01/14 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +fr 1 320 01/14 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +fr 1 321 01/14 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +fr 1 322 01/14 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +fr 1 323 01/14 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +fr 1 324 01/14 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +fr 1 325 01/14 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +fr 1 326 01/14 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +fr 1 327 01/14 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +fr 1 328 01/14 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +fr 1 329 01/14 16:00 720000.0 720000.0 89.99 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +fr 1 330 01/14 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +fr 1 331 01/14 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +fr 1 332 01/14 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +fr 1 333 01/14 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +fr 1 334 01/14 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +fr 1 335 01/14 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +fr 1 336 01/14 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 +it 1 1 01/01 00:00 0.0 0.0 10.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +it 1 2 01/01 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +it 1 3 01/01 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +it 1 4 01/01 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +it 1 5 01/01 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +it 1 6 01/01 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +it 1 7 01/01 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +it 1 8 01/01 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +it 1 9 01/01 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +it 1 10 01/01 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +it 1 11 01/01 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +it 1 12 01/01 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +it 1 13 01/01 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +it 1 14 01/01 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +it 1 15 01/01 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +it 1 16 01/01 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +it 1 17 01/01 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +it 1 18 01/01 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +it 1 19 01/01 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +it 1 20 01/01 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +it 1 21 01/01 20:00 20000.0 20000.0 20.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +it 1 22 01/01 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +it 1 23 01/01 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +it 1 24 01/01 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +it 1 25 01/02 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +it 1 26 01/02 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +it 1 27 01/02 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +it 1 28 01/02 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +it 1 29 01/02 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +it 1 30 01/02 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +it 1 31 01/02 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +it 1 32 01/02 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +it 1 33 01/02 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +it 1 34 01/02 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +it 1 35 01/02 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +it 1 36 01/02 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +it 1 37 01/02 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +it 1 38 01/02 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +it 1 39 01/02 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +it 1 40 01/02 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +it 1 41 01/02 16:00 60000.0 60000.0 30.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +it 1 42 01/02 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +it 1 43 01/02 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +it 1 44 01/02 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +it 1 45 01/02 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +it 1 46 01/02 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +it 1 47 01/02 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +it 1 48 01/02 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +it 1 49 01/03 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +it 1 50 01/03 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +it 1 51 01/03 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +it 1 52 01/03 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +it 1 53 01/03 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +it 1 54 01/03 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +it 1 55 01/03 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +it 1 56 01/03 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +it 1 57 01/03 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +it 1 58 01/03 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +it 1 59 01/03 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +it 1 60 01/03 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +it 1 61 01/03 12:00 120000.0 120000.0 40.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +it 1 62 01/03 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +it 1 63 01/03 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +it 1 64 01/03 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +it 1 65 01/03 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +it 1 66 01/03 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +it 1 67 01/03 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +it 1 68 01/03 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +it 1 69 01/03 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +it 1 70 01/03 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +it 1 71 01/03 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +it 1 72 01/03 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +it 1 73 01/04 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +it 1 74 01/04 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +it 1 75 01/04 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +it 1 76 01/04 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +it 1 77 01/04 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +it 1 78 01/04 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +it 1 79 01/04 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +it 1 80 01/04 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +it 1 81 01/04 08:00 200000.0 200000.0 50.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +it 1 82 01/04 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +it 1 83 01/04 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +it 1 84 01/04 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +it 1 85 01/04 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +it 1 86 01/04 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +it 1 87 01/04 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +it 1 88 01/04 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +it 1 89 01/04 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +it 1 90 01/04 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +it 1 91 01/04 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +it 1 92 01/04 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +it 1 93 01/04 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +it 1 94 01/04 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +it 1 95 01/04 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +it 1 96 01/04 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +it 1 97 01/05 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +it 1 98 01/05 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +it 1 99 01/05 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +it 1 100 01/05 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +it 1 101 01/05 04:00 300000.0 300000.0 60.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +it 1 102 01/05 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +it 1 103 01/05 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +it 1 104 01/05 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +it 1 105 01/05 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +it 1 106 01/05 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +it 1 107 01/05 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +it 1 108 01/05 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +it 1 109 01/05 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +it 1 110 01/05 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +it 1 111 01/05 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +it 1 112 01/05 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +it 1 113 01/05 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +it 1 114 01/05 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +it 1 115 01/05 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +it 1 116 01/05 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +it 1 117 01/05 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +it 1 118 01/05 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +it 1 119 01/05 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +it 1 120 01/05 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +it 1 121 01/06 00:00 420000.0 420000.0 70.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +it 1 122 01/06 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +it 1 123 01/06 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +it 1 124 01/06 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +it 1 125 01/06 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +it 1 126 01/06 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +it 1 127 01/06 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +it 1 128 01/06 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +it 1 129 01/06 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +it 1 130 01/06 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +it 1 131 01/06 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +it 1 132 01/06 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +it 1 133 01/06 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +it 1 134 01/06 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +it 1 135 01/06 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +it 1 136 01/06 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +it 1 137 01/06 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +it 1 138 01/06 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +it 1 139 01/06 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +it 1 140 01/06 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +it 1 141 01/06 20:00 560000.0 560000.0 80.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +it 1 142 01/06 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +it 1 143 01/06 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +it 1 144 01/06 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +it 1 145 01/07 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +it 1 146 01/07 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +it 1 147 01/07 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +it 1 148 01/07 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +it 1 149 01/07 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +it 1 150 01/07 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +it 1 151 01/07 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +it 1 152 01/07 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +it 1 153 01/07 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +it 1 154 01/07 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +it 1 155 01/07 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +it 1 156 01/07 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +it 1 157 01/07 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +it 1 158 01/07 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +it 1 159 01/07 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +it 1 160 01/07 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +it 1 161 01/07 16:00 720000.0 720000.0 90.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +it 1 162 01/07 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +it 1 163 01/07 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +it 1 164 01/07 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +it 1 165 01/07 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +it 1 166 01/07 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +it 1 167 01/07 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +it 1 168 01/07 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 +it 1 169 01/08 00:00 0.0 0.0 10.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +it 1 170 01/08 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +it 1 171 01/08 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +it 1 172 01/08 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +it 1 173 01/08 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +it 1 174 01/08 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +it 1 175 01/08 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +it 1 176 01/08 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +it 1 177 01/08 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +it 1 178 01/08 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +it 1 179 01/08 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +it 1 180 01/08 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +it 1 181 01/08 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +it 1 182 01/08 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +it 1 183 01/08 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +it 1 184 01/08 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +it 1 185 01/08 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +it 1 186 01/08 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +it 1 187 01/08 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +it 1 188 01/08 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +it 1 189 01/08 20:00 20000.0 20000.0 20.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +it 1 190 01/08 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +it 1 191 01/08 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +it 1 192 01/08 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +it 1 193 01/09 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +it 1 194 01/09 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +it 1 195 01/09 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +it 1 196 01/09 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +it 1 197 01/09 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +it 1 198 01/09 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +it 1 199 01/09 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +it 1 200 01/09 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +it 1 201 01/09 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +it 1 202 01/09 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +it 1 203 01/09 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +it 1 204 01/09 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +it 1 205 01/09 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +it 1 206 01/09 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +it 1 207 01/09 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +it 1 208 01/09 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +it 1 209 01/09 16:00 60000.0 60000.0 30.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +it 1 210 01/09 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +it 1 211 01/09 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +it 1 212 01/09 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +it 1 213 01/09 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +it 1 214 01/09 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +it 1 215 01/09 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +it 1 216 01/09 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +it 1 217 01/10 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +it 1 218 01/10 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +it 1 219 01/10 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +it 1 220 01/10 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +it 1 221 01/10 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +it 1 222 01/10 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +it 1 223 01/10 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +it 1 224 01/10 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +it 1 225 01/10 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +it 1 226 01/10 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +it 1 227 01/10 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +it 1 228 01/10 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +it 1 229 01/10 12:00 120000.0 120000.0 40.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +it 1 230 01/10 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +it 1 231 01/10 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +it 1 232 01/10 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +it 1 233 01/10 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +it 1 234 01/10 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +it 1 235 01/10 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +it 1 236 01/10 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +it 1 237 01/10 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +it 1 238 01/10 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +it 1 239 01/10 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +it 1 240 01/10 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +it 1 241 01/11 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +it 1 242 01/11 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +it 1 243 01/11 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +it 1 244 01/11 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +it 1 245 01/11 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +it 1 246 01/11 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +it 1 247 01/11 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +it 1 248 01/11 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +it 1 249 01/11 08:00 200000.0 200000.0 50.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +it 1 250 01/11 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +it 1 251 01/11 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +it 1 252 01/11 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +it 1 253 01/11 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +it 1 254 01/11 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +it 1 255 01/11 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +it 1 256 01/11 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +it 1 257 01/11 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +it 1 258 01/11 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +it 1 259 01/11 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +it 1 260 01/11 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +it 1 261 01/11 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +it 1 262 01/11 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +it 1 263 01/11 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +it 1 264 01/11 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +it 1 265 01/12 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +it 1 266 01/12 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +it 1 267 01/12 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +it 1 268 01/12 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +it 1 269 01/12 04:00 300000.0 300000.0 60.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +it 1 270 01/12 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +it 1 271 01/12 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +it 1 272 01/12 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +it 1 273 01/12 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +it 1 274 01/12 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +it 1 275 01/12 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +it 1 276 01/12 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +it 1 277 01/12 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +it 1 278 01/12 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +it 1 279 01/12 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +it 1 280 01/12 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +it 1 281 01/12 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +it 1 282 01/12 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +it 1 283 01/12 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +it 1 284 01/12 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +it 1 285 01/12 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +it 1 286 01/12 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +it 1 287 01/12 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +it 1 288 01/12 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +it 1 289 01/13 00:00 420000.0 420000.0 70.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +it 1 290 01/13 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +it 1 291 01/13 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +it 1 292 01/13 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +it 1 293 01/13 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +it 1 294 01/13 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +it 1 295 01/13 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +it 1 296 01/13 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +it 1 297 01/13 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +it 1 298 01/13 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +it 1 299 01/13 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +it 1 300 01/13 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +it 1 301 01/13 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +it 1 302 01/13 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +it 1 303 01/13 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +it 1 304 01/13 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +it 1 305 01/13 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +it 1 306 01/13 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +it 1 307 01/13 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +it 1 308 01/13 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +it 1 309 01/13 20:00 560000.0 560000.0 80.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +it 1 310 01/13 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +it 1 311 01/13 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +it 1 312 01/13 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +it 1 313 01/14 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +it 1 314 01/14 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +it 1 315 01/14 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +it 1 316 01/14 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +it 1 317 01/14 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +it 1 318 01/14 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +it 1 319 01/14 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +it 1 320 01/14 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +it 1 321 01/14 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +it 1 322 01/14 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +it 1 323 01/14 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +it 1 324 01/14 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +it 1 325 01/14 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +it 1 326 01/14 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +it 1 327 01/14 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +it 1 328 01/14 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +it 1 329 01/14 16:00 720000.0 720000.0 90.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +it 1 330 01/14 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +it 1 331 01/14 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +it 1 332 01/14 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +it 1 333 01/14 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +it 1 334 01/14 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +it 1 335 01/14 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +it 1 336 01/14 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 +de 2 1 01/01 00:00 0.0 0.0 9.98 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +de 2 2 01/01 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +de 2 3 01/01 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +de 2 4 01/01 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +de 2 5 01/01 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +de 2 6 01/01 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +de 2 7 01/01 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +de 2 8 01/01 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +de 2 9 01/01 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +de 2 10 01/01 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +de 2 11 01/01 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +de 2 12 01/01 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +de 2 13 01/01 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +de 2 14 01/01 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +de 2 15 01/01 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +de 2 16 01/01 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +de 2 17 01/01 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +de 2 18 01/01 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +de 2 19 01/01 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +de 2 20 01/01 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +de 2 21 01/01 20:00 20000.0 20000.0 19.98 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +de 2 22 01/01 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +de 2 23 01/01 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +de 2 24 01/01 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +de 2 25 01/02 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +de 2 26 01/02 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +de 2 27 01/02 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +de 2 28 01/02 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +de 2 29 01/02 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +de 2 30 01/02 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +de 2 31 01/02 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +de 2 32 01/02 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +de 2 33 01/02 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +de 2 34 01/02 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +de 2 35 01/02 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +de 2 36 01/02 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +de 2 37 01/02 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +de 2 38 01/02 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +de 2 39 01/02 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +de 2 40 01/02 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +de 2 41 01/02 16:00 60000.0 60000.0 29.98 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +de 2 42 01/02 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +de 2 43 01/02 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +de 2 44 01/02 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +de 2 45 01/02 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +de 2 46 01/02 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +de 2 47 01/02 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +de 2 48 01/02 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +de 2 49 01/03 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +de 2 50 01/03 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +de 2 51 01/03 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +de 2 52 01/03 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +de 2 53 01/03 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +de 2 54 01/03 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +de 2 55 01/03 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +de 2 56 01/03 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +de 2 57 01/03 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +de 2 58 01/03 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +de 2 59 01/03 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +de 2 60 01/03 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +de 2 61 01/03 12:00 120000.0 120000.0 39.98 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +de 2 62 01/03 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +de 2 63 01/03 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +de 2 64 01/03 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +de 2 65 01/03 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +de 2 66 01/03 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +de 2 67 01/03 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +de 2 68 01/03 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +de 2 69 01/03 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +de 2 70 01/03 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +de 2 71 01/03 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +de 2 72 01/03 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +de 2 73 01/04 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +de 2 74 01/04 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +de 2 75 01/04 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +de 2 76 01/04 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +de 2 77 01/04 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +de 2 78 01/04 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +de 2 79 01/04 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +de 2 80 01/04 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +de 2 81 01/04 08:00 200000.0 200000.0 49.98 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +de 2 82 01/04 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +de 2 83 01/04 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +de 2 84 01/04 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +de 2 85 01/04 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +de 2 86 01/04 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +de 2 87 01/04 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +de 2 88 01/04 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +de 2 89 01/04 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +de 2 90 01/04 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +de 2 91 01/04 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +de 2 92 01/04 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +de 2 93 01/04 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +de 2 94 01/04 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +de 2 95 01/04 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +de 2 96 01/04 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +de 2 97 01/05 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +de 2 98 01/05 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +de 2 99 01/05 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +de 2 100 01/05 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +de 2 101 01/05 04:00 300000.0 300000.0 59.98 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +de 2 102 01/05 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +de 2 103 01/05 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +de 2 104 01/05 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +de 2 105 01/05 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +de 2 106 01/05 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +de 2 107 01/05 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +de 2 108 01/05 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +de 2 109 01/05 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +de 2 110 01/05 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +de 2 111 01/05 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +de 2 112 01/05 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +de 2 113 01/05 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +de 2 114 01/05 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +de 2 115 01/05 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +de 2 116 01/05 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +de 2 117 01/05 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +de 2 118 01/05 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +de 2 119 01/05 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +de 2 120 01/05 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +de 2 121 01/06 00:00 420000.0 420000.0 69.98 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +de 2 122 01/06 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +de 2 123 01/06 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +de 2 124 01/06 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +de 2 125 01/06 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +de 2 126 01/06 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +de 2 127 01/06 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +de 2 128 01/06 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +de 2 129 01/06 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +de 2 130 01/06 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +de 2 131 01/06 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +de 2 132 01/06 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +de 2 133 01/06 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +de 2 134 01/06 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +de 2 135 01/06 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +de 2 136 01/06 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +de 2 137 01/06 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +de 2 138 01/06 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +de 2 139 01/06 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +de 2 140 01/06 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +de 2 141 01/06 20:00 560000.0 560000.0 79.98 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +de 2 142 01/06 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +de 2 143 01/06 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +de 2 144 01/06 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +de 2 145 01/07 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +de 2 146 01/07 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +de 2 147 01/07 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +de 2 148 01/07 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +de 2 149 01/07 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +de 2 150 01/07 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +de 2 151 01/07 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +de 2 152 01/07 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +de 2 153 01/07 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +de 2 154 01/07 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +de 2 155 01/07 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +de 2 156 01/07 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +de 2 157 01/07 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +de 2 158 01/07 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +de 2 159 01/07 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +de 2 160 01/07 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +de 2 161 01/07 16:00 720000.0 720000.0 89.98 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +de 2 162 01/07 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +de 2 163 01/07 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +de 2 164 01/07 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +de 2 165 01/07 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +de 2 166 01/07 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +de 2 167 01/07 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +de 2 168 01/07 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 +de 2 169 01/08 00:00 0.0 0.0 9.98 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +de 2 170 01/08 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +de 2 171 01/08 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +de 2 172 01/08 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +de 2 173 01/08 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +de 2 174 01/08 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +de 2 175 01/08 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +de 2 176 01/08 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +de 2 177 01/08 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +de 2 178 01/08 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +de 2 179 01/08 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +de 2 180 01/08 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +de 2 181 01/08 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +de 2 182 01/08 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +de 2 183 01/08 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +de 2 184 01/08 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +de 2 185 01/08 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +de 2 186 01/08 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +de 2 187 01/08 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +de 2 188 01/08 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +de 2 189 01/08 20:00 20000.0 20000.0 19.98 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +de 2 190 01/08 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +de 2 191 01/08 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +de 2 192 01/08 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +de 2 193 01/09 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +de 2 194 01/09 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +de 2 195 01/09 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +de 2 196 01/09 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +de 2 197 01/09 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +de 2 198 01/09 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +de 2 199 01/09 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +de 2 200 01/09 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +de 2 201 01/09 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +de 2 202 01/09 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +de 2 203 01/09 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +de 2 204 01/09 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +de 2 205 01/09 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +de 2 206 01/09 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +de 2 207 01/09 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +de 2 208 01/09 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +de 2 209 01/09 16:00 60000.0 60000.0 29.98 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +de 2 210 01/09 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +de 2 211 01/09 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +de 2 212 01/09 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +de 2 213 01/09 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +de 2 214 01/09 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +de 2 215 01/09 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +de 2 216 01/09 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +de 2 217 01/10 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +de 2 218 01/10 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +de 2 219 01/10 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +de 2 220 01/10 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +de 2 221 01/10 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +de 2 222 01/10 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +de 2 223 01/10 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +de 2 224 01/10 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +de 2 225 01/10 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +de 2 226 01/10 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +de 2 227 01/10 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +de 2 228 01/10 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +de 2 229 01/10 12:00 120000.0 120000.0 39.98 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +de 2 230 01/10 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +de 2 231 01/10 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +de 2 232 01/10 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +de 2 233 01/10 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +de 2 234 01/10 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +de 2 235 01/10 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +de 2 236 01/10 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +de 2 237 01/10 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +de 2 238 01/10 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +de 2 239 01/10 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +de 2 240 01/10 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +de 2 241 01/11 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +de 2 242 01/11 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +de 2 243 01/11 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +de 2 244 01/11 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +de 2 245 01/11 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +de 2 246 01/11 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +de 2 247 01/11 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +de 2 248 01/11 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +de 2 249 01/11 08:00 200000.0 200000.0 49.98 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +de 2 250 01/11 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +de 2 251 01/11 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +de 2 252 01/11 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +de 2 253 01/11 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +de 2 254 01/11 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +de 2 255 01/11 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +de 2 256 01/11 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +de 2 257 01/11 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +de 2 258 01/11 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +de 2 259 01/11 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +de 2 260 01/11 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +de 2 261 01/11 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +de 2 262 01/11 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +de 2 263 01/11 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +de 2 264 01/11 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +de 2 265 01/12 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +de 2 266 01/12 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +de 2 267 01/12 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +de 2 268 01/12 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +de 2 269 01/12 04:00 300000.0 300000.0 59.98 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +de 2 270 01/12 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +de 2 271 01/12 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +de 2 272 01/12 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +de 2 273 01/12 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +de 2 274 01/12 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +de 2 275 01/12 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +de 2 276 01/12 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +de 2 277 01/12 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +de 2 278 01/12 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +de 2 279 01/12 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +de 2 280 01/12 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +de 2 281 01/12 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +de 2 282 01/12 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +de 2 283 01/12 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +de 2 284 01/12 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +de 2 285 01/12 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +de 2 286 01/12 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +de 2 287 01/12 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +de 2 288 01/12 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +de 2 289 01/13 00:00 420000.0 420000.0 69.98 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +de 2 290 01/13 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +de 2 291 01/13 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +de 2 292 01/13 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +de 2 293 01/13 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +de 2 294 01/13 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +de 2 295 01/13 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +de 2 296 01/13 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +de 2 297 01/13 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +de 2 298 01/13 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +de 2 299 01/13 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +de 2 300 01/13 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +de 2 301 01/13 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +de 2 302 01/13 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +de 2 303 01/13 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +de 2 304 01/13 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +de 2 305 01/13 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +de 2 306 01/13 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +de 2 307 01/13 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +de 2 308 01/13 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +de 2 309 01/13 20:00 560000.0 560000.0 79.98 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +de 2 310 01/13 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +de 2 311 01/13 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +de 2 312 01/13 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +de 2 313 01/14 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +de 2 314 01/14 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +de 2 315 01/14 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +de 2 316 01/14 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +de 2 317 01/14 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +de 2 318 01/14 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +de 2 319 01/14 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +de 2 320 01/14 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +de 2 321 01/14 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +de 2 322 01/14 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +de 2 323 01/14 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +de 2 324 01/14 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +de 2 325 01/14 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +de 2 326 01/14 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +de 2 327 01/14 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +de 2 328 01/14 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +de 2 329 01/14 16:00 720000.0 720000.0 89.98 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +de 2 330 01/14 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +de 2 331 01/14 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +de 2 332 01/14 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +de 2 333 01/14 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +de 2 334 01/14 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +de 2 335 01/14 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +de 2 336 01/14 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 +es 2 1 01/01 00:00 0.0 0.0 9.98 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +es 2 2 01/01 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +es 2 3 01/01 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +es 2 4 01/01 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +es 2 5 01/01 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +es 2 6 01/01 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +es 2 7 01/01 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +es 2 8 01/01 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +es 2 9 01/01 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +es 2 10 01/01 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +es 2 11 01/01 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +es 2 12 01/01 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +es 2 13 01/01 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +es 2 14 01/01 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +es 2 15 01/01 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +es 2 16 01/01 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +es 2 17 01/01 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +es 2 18 01/01 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +es 2 19 01/01 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +es 2 20 01/01 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +es 2 21 01/01 20:00 20000.0 20000.0 19.98 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +es 2 22 01/01 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +es 2 23 01/01 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +es 2 24 01/01 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +es 2 25 01/02 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +es 2 26 01/02 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +es 2 27 01/02 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +es 2 28 01/02 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +es 2 29 01/02 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +es 2 30 01/02 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +es 2 31 01/02 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +es 2 32 01/02 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +es 2 33 01/02 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +es 2 34 01/02 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +es 2 35 01/02 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +es 2 36 01/02 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +es 2 37 01/02 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +es 2 38 01/02 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +es 2 39 01/02 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +es 2 40 01/02 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +es 2 41 01/02 16:00 60000.0 60000.0 29.98 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +es 2 42 01/02 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +es 2 43 01/02 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +es 2 44 01/02 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +es 2 45 01/02 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +es 2 46 01/02 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +es 2 47 01/02 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +es 2 48 01/02 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +es 2 49 01/03 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +es 2 50 01/03 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +es 2 51 01/03 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +es 2 52 01/03 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +es 2 53 01/03 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +es 2 54 01/03 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +es 2 55 01/03 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +es 2 56 01/03 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +es 2 57 01/03 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +es 2 58 01/03 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +es 2 59 01/03 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +es 2 60 01/03 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +es 2 61 01/03 12:00 120000.0 120000.0 39.98 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +es 2 62 01/03 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +es 2 63 01/03 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +es 2 64 01/03 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +es 2 65 01/03 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +es 2 66 01/03 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +es 2 67 01/03 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +es 2 68 01/03 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +es 2 69 01/03 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +es 2 70 01/03 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +es 2 71 01/03 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +es 2 72 01/03 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +es 2 73 01/04 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +es 2 74 01/04 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +es 2 75 01/04 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +es 2 76 01/04 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +es 2 77 01/04 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +es 2 78 01/04 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +es 2 79 01/04 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +es 2 80 01/04 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +es 2 81 01/04 08:00 200000.0 200000.0 49.98 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +es 2 82 01/04 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +es 2 83 01/04 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +es 2 84 01/04 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +es 2 85 01/04 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +es 2 86 01/04 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +es 2 87 01/04 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +es 2 88 01/04 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +es 2 89 01/04 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +es 2 90 01/04 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +es 2 91 01/04 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +es 2 92 01/04 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +es 2 93 01/04 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +es 2 94 01/04 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +es 2 95 01/04 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +es 2 96 01/04 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +es 2 97 01/05 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +es 2 98 01/05 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +es 2 99 01/05 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +es 2 100 01/05 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +es 2 101 01/05 04:00 300000.0 300000.0 59.98 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +es 2 102 01/05 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +es 2 103 01/05 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +es 2 104 01/05 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +es 2 105 01/05 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +es 2 106 01/05 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +es 2 107 01/05 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +es 2 108 01/05 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +es 2 109 01/05 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +es 2 110 01/05 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +es 2 111 01/05 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +es 2 112 01/05 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +es 2 113 01/05 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +es 2 114 01/05 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +es 2 115 01/05 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +es 2 116 01/05 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +es 2 117 01/05 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +es 2 118 01/05 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +es 2 119 01/05 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +es 2 120 01/05 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +es 2 121 01/06 00:00 420000.0 420000.0 69.98 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +es 2 122 01/06 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +es 2 123 01/06 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +es 2 124 01/06 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +es 2 125 01/06 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +es 2 126 01/06 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +es 2 127 01/06 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +es 2 128 01/06 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +es 2 129 01/06 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +es 2 130 01/06 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +es 2 131 01/06 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +es 2 132 01/06 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +es 2 133 01/06 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +es 2 134 01/06 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +es 2 135 01/06 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +es 2 136 01/06 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +es 2 137 01/06 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +es 2 138 01/06 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +es 2 139 01/06 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +es 2 140 01/06 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +es 2 141 01/06 20:00 560000.0 560000.0 79.98 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +es 2 142 01/06 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +es 2 143 01/06 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +es 2 144 01/06 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +es 2 145 01/07 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +es 2 146 01/07 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +es 2 147 01/07 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +es 2 148 01/07 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +es 2 149 01/07 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +es 2 150 01/07 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +es 2 151 01/07 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +es 2 152 01/07 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +es 2 153 01/07 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +es 2 154 01/07 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +es 2 155 01/07 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +es 2 156 01/07 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +es 2 157 01/07 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +es 2 158 01/07 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +es 2 159 01/07 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +es 2 160 01/07 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +es 2 161 01/07 16:00 720000.0 720000.0 89.98 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +es 2 162 01/07 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +es 2 163 01/07 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +es 2 164 01/07 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +es 2 165 01/07 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +es 2 166 01/07 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +es 2 167 01/07 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +es 2 168 01/07 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 +es 2 169 01/08 00:00 0.0 0.0 9.98 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +es 2 170 01/08 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +es 2 171 01/08 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +es 2 172 01/08 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +es 2 173 01/08 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +es 2 174 01/08 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +es 2 175 01/08 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +es 2 176 01/08 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +es 2 177 01/08 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +es 2 178 01/08 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +es 2 179 01/08 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +es 2 180 01/08 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +es 2 181 01/08 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +es 2 182 01/08 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +es 2 183 01/08 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +es 2 184 01/08 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +es 2 185 01/08 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +es 2 186 01/08 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +es 2 187 01/08 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +es 2 188 01/08 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +es 2 189 01/08 20:00 20000.0 20000.0 19.98 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +es 2 190 01/08 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +es 2 191 01/08 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +es 2 192 01/08 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +es 2 193 01/09 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +es 2 194 01/09 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +es 2 195 01/09 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +es 2 196 01/09 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +es 2 197 01/09 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +es 2 198 01/09 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +es 2 199 01/09 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +es 2 200 01/09 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +es 2 201 01/09 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +es 2 202 01/09 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +es 2 203 01/09 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +es 2 204 01/09 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +es 2 205 01/09 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +es 2 206 01/09 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +es 2 207 01/09 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +es 2 208 01/09 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +es 2 209 01/09 16:00 60000.0 60000.0 29.98 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +es 2 210 01/09 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +es 2 211 01/09 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +es 2 212 01/09 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +es 2 213 01/09 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +es 2 214 01/09 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +es 2 215 01/09 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +es 2 216 01/09 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +es 2 217 01/10 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +es 2 218 01/10 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +es 2 219 01/10 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +es 2 220 01/10 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +es 2 221 01/10 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +es 2 222 01/10 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +es 2 223 01/10 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +es 2 224 01/10 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +es 2 225 01/10 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +es 2 226 01/10 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +es 2 227 01/10 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +es 2 228 01/10 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +es 2 229 01/10 12:00 120000.0 120000.0 39.98 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +es 2 230 01/10 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +es 2 231 01/10 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +es 2 232 01/10 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +es 2 233 01/10 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +es 2 234 01/10 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +es 2 235 01/10 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +es 2 236 01/10 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +es 2 237 01/10 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +es 2 238 01/10 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +es 2 239 01/10 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +es 2 240 01/10 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +es 2 241 01/11 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +es 2 242 01/11 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +es 2 243 01/11 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +es 2 244 01/11 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +es 2 245 01/11 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +es 2 246 01/11 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +es 2 247 01/11 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +es 2 248 01/11 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +es 2 249 01/11 08:00 200000.0 200000.0 49.98 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +es 2 250 01/11 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +es 2 251 01/11 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +es 2 252 01/11 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +es 2 253 01/11 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +es 2 254 01/11 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +es 2 255 01/11 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +es 2 256 01/11 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +es 2 257 01/11 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +es 2 258 01/11 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +es 2 259 01/11 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +es 2 260 01/11 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +es 2 261 01/11 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +es 2 262 01/11 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +es 2 263 01/11 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +es 2 264 01/11 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +es 2 265 01/12 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +es 2 266 01/12 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +es 2 267 01/12 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +es 2 268 01/12 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +es 2 269 01/12 04:00 300000.0 300000.0 59.98 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +es 2 270 01/12 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +es 2 271 01/12 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +es 2 272 01/12 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +es 2 273 01/12 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +es 2 274 01/12 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +es 2 275 01/12 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +es 2 276 01/12 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +es 2 277 01/12 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +es 2 278 01/12 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +es 2 279 01/12 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +es 2 280 01/12 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +es 2 281 01/12 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +es 2 282 01/12 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +es 2 283 01/12 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +es 2 284 01/12 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +es 2 285 01/12 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +es 2 286 01/12 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +es 2 287 01/12 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +es 2 288 01/12 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +es 2 289 01/13 00:00 420000.0 420000.0 69.98 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +es 2 290 01/13 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +es 2 291 01/13 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +es 2 292 01/13 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +es 2 293 01/13 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +es 2 294 01/13 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +es 2 295 01/13 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +es 2 296 01/13 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +es 2 297 01/13 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +es 2 298 01/13 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +es 2 299 01/13 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +es 2 300 01/13 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +es 2 301 01/13 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +es 2 302 01/13 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +es 2 303 01/13 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +es 2 304 01/13 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +es 2 305 01/13 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +es 2 306 01/13 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +es 2 307 01/13 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +es 2 308 01/13 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +es 2 309 01/13 20:00 560000.0 560000.0 79.98 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +es 2 310 01/13 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +es 2 311 01/13 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +es 2 312 01/13 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +es 2 313 01/14 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +es 2 314 01/14 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +es 2 315 01/14 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +es 2 316 01/14 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +es 2 317 01/14 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +es 2 318 01/14 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +es 2 319 01/14 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +es 2 320 01/14 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +es 2 321 01/14 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +es 2 322 01/14 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +es 2 323 01/14 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +es 2 324 01/14 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +es 2 325 01/14 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +es 2 326 01/14 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +es 2 327 01/14 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +es 2 328 01/14 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +es 2 329 01/14 16:00 720000.0 720000.0 89.98 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +es 2 330 01/14 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +es 2 331 01/14 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +es 2 332 01/14 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +es 2 333 01/14 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +es 2 334 01/14 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +es 2 335 01/14 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +es 2 336 01/14 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 +fr 2 1 01/01 00:00 0.0 0.0 9.99 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +fr 2 2 01/01 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +fr 2 3 01/01 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +fr 2 4 01/01 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +fr 2 5 01/01 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +fr 2 6 01/01 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +fr 2 7 01/01 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +fr 2 8 01/01 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +fr 2 9 01/01 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +fr 2 10 01/01 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +fr 2 11 01/01 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +fr 2 12 01/01 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +fr 2 13 01/01 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +fr 2 14 01/01 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +fr 2 15 01/01 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +fr 2 16 01/01 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +fr 2 17 01/01 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +fr 2 18 01/01 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +fr 2 19 01/01 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +fr 2 20 01/01 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +fr 2 21 01/01 20:00 20000.0 20000.0 19.99 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +fr 2 22 01/01 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +fr 2 23 01/01 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +fr 2 24 01/01 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +fr 2 25 01/02 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +fr 2 26 01/02 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +fr 2 27 01/02 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +fr 2 28 01/02 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +fr 2 29 01/02 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +fr 2 30 01/02 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +fr 2 31 01/02 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +fr 2 32 01/02 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +fr 2 33 01/02 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +fr 2 34 01/02 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +fr 2 35 01/02 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +fr 2 36 01/02 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +fr 2 37 01/02 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +fr 2 38 01/02 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +fr 2 39 01/02 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +fr 2 40 01/02 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +fr 2 41 01/02 16:00 60000.0 60000.0 29.99 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +fr 2 42 01/02 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +fr 2 43 01/02 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +fr 2 44 01/02 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +fr 2 45 01/02 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +fr 2 46 01/02 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +fr 2 47 01/02 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +fr 2 48 01/02 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +fr 2 49 01/03 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +fr 2 50 01/03 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +fr 2 51 01/03 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +fr 2 52 01/03 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +fr 2 53 01/03 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +fr 2 54 01/03 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +fr 2 55 01/03 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +fr 2 56 01/03 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +fr 2 57 01/03 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +fr 2 58 01/03 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +fr 2 59 01/03 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +fr 2 60 01/03 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +fr 2 61 01/03 12:00 120000.0 120000.0 39.99 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +fr 2 62 01/03 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +fr 2 63 01/03 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +fr 2 64 01/03 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +fr 2 65 01/03 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +fr 2 66 01/03 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +fr 2 67 01/03 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +fr 2 68 01/03 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +fr 2 69 01/03 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +fr 2 70 01/03 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +fr 2 71 01/03 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +fr 2 72 01/03 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +fr 2 73 01/04 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +fr 2 74 01/04 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +fr 2 75 01/04 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +fr 2 76 01/04 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +fr 2 77 01/04 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +fr 2 78 01/04 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +fr 2 79 01/04 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +fr 2 80 01/04 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +fr 2 81 01/04 08:00 200000.0 200000.0 49.99 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +fr 2 82 01/04 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +fr 2 83 01/04 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +fr 2 84 01/04 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +fr 2 85 01/04 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +fr 2 86 01/04 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +fr 2 87 01/04 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +fr 2 88 01/04 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +fr 2 89 01/04 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +fr 2 90 01/04 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +fr 2 91 01/04 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +fr 2 92 01/04 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +fr 2 93 01/04 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +fr 2 94 01/04 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +fr 2 95 01/04 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +fr 2 96 01/04 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +fr 2 97 01/05 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +fr 2 98 01/05 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +fr 2 99 01/05 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +fr 2 100 01/05 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +fr 2 101 01/05 04:00 300000.0 300000.0 59.99 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +fr 2 102 01/05 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +fr 2 103 01/05 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +fr 2 104 01/05 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +fr 2 105 01/05 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +fr 2 106 01/05 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +fr 2 107 01/05 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +fr 2 108 01/05 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +fr 2 109 01/05 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +fr 2 110 01/05 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +fr 2 111 01/05 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +fr 2 112 01/05 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +fr 2 113 01/05 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +fr 2 114 01/05 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +fr 2 115 01/05 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +fr 2 116 01/05 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +fr 2 117 01/05 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +fr 2 118 01/05 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +fr 2 119 01/05 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +fr 2 120 01/05 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +fr 2 121 01/06 00:00 420000.0 420000.0 69.99 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +fr 2 122 01/06 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +fr 2 123 01/06 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +fr 2 124 01/06 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +fr 2 125 01/06 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +fr 2 126 01/06 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +fr 2 127 01/06 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +fr 2 128 01/06 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +fr 2 129 01/06 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +fr 2 130 01/06 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +fr 2 131 01/06 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +fr 2 132 01/06 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +fr 2 133 01/06 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +fr 2 134 01/06 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +fr 2 135 01/06 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +fr 2 136 01/06 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +fr 2 137 01/06 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +fr 2 138 01/06 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +fr 2 139 01/06 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +fr 2 140 01/06 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +fr 2 141 01/06 20:00 560000.0 560000.0 79.99 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +fr 2 142 01/06 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +fr 2 143 01/06 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +fr 2 144 01/06 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +fr 2 145 01/07 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +fr 2 146 01/07 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +fr 2 147 01/07 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +fr 2 148 01/07 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +fr 2 149 01/07 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +fr 2 150 01/07 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +fr 2 151 01/07 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +fr 2 152 01/07 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +fr 2 153 01/07 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +fr 2 154 01/07 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +fr 2 155 01/07 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +fr 2 156 01/07 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +fr 2 157 01/07 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +fr 2 158 01/07 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +fr 2 159 01/07 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +fr 2 160 01/07 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +fr 2 161 01/07 16:00 720000.0 720000.0 89.99 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +fr 2 162 01/07 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +fr 2 163 01/07 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +fr 2 164 01/07 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +fr 2 165 01/07 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +fr 2 166 01/07 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +fr 2 167 01/07 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +fr 2 168 01/07 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 +fr 2 169 01/08 00:00 0.0 0.0 9.99 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +fr 2 170 01/08 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +fr 2 171 01/08 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +fr 2 172 01/08 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +fr 2 173 01/08 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +fr 2 174 01/08 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +fr 2 175 01/08 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +fr 2 176 01/08 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +fr 2 177 01/08 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +fr 2 178 01/08 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +fr 2 179 01/08 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +fr 2 180 01/08 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +fr 2 181 01/08 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +fr 2 182 01/08 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +fr 2 183 01/08 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +fr 2 184 01/08 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +fr 2 185 01/08 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +fr 2 186 01/08 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +fr 2 187 01/08 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +fr 2 188 01/08 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +fr 2 189 01/08 20:00 20000.0 20000.0 19.99 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +fr 2 190 01/08 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +fr 2 191 01/08 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +fr 2 192 01/08 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +fr 2 193 01/09 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +fr 2 194 01/09 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +fr 2 195 01/09 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +fr 2 196 01/09 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +fr 2 197 01/09 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +fr 2 198 01/09 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +fr 2 199 01/09 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +fr 2 200 01/09 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +fr 2 201 01/09 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +fr 2 202 01/09 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +fr 2 203 01/09 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +fr 2 204 01/09 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +fr 2 205 01/09 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +fr 2 206 01/09 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +fr 2 207 01/09 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +fr 2 208 01/09 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +fr 2 209 01/09 16:00 60000.0 60000.0 29.99 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +fr 2 210 01/09 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +fr 2 211 01/09 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +fr 2 212 01/09 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +fr 2 213 01/09 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +fr 2 214 01/09 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +fr 2 215 01/09 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +fr 2 216 01/09 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +fr 2 217 01/10 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +fr 2 218 01/10 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +fr 2 219 01/10 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +fr 2 220 01/10 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +fr 2 221 01/10 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +fr 2 222 01/10 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +fr 2 223 01/10 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +fr 2 224 01/10 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +fr 2 225 01/10 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +fr 2 226 01/10 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +fr 2 227 01/10 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +fr 2 228 01/10 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +fr 2 229 01/10 12:00 120000.0 120000.0 39.99 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +fr 2 230 01/10 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +fr 2 231 01/10 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +fr 2 232 01/10 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +fr 2 233 01/10 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +fr 2 234 01/10 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +fr 2 235 01/10 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +fr 2 236 01/10 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +fr 2 237 01/10 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +fr 2 238 01/10 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +fr 2 239 01/10 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +fr 2 240 01/10 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +fr 2 241 01/11 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +fr 2 242 01/11 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +fr 2 243 01/11 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +fr 2 244 01/11 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +fr 2 245 01/11 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +fr 2 246 01/11 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +fr 2 247 01/11 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +fr 2 248 01/11 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +fr 2 249 01/11 08:00 200000.0 200000.0 49.99 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +fr 2 250 01/11 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +fr 2 251 01/11 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +fr 2 252 01/11 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +fr 2 253 01/11 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +fr 2 254 01/11 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +fr 2 255 01/11 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +fr 2 256 01/11 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +fr 2 257 01/11 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +fr 2 258 01/11 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +fr 2 259 01/11 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +fr 2 260 01/11 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +fr 2 261 01/11 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +fr 2 262 01/11 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +fr 2 263 01/11 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +fr 2 264 01/11 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +fr 2 265 01/12 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +fr 2 266 01/12 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +fr 2 267 01/12 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +fr 2 268 01/12 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +fr 2 269 01/12 04:00 300000.0 300000.0 59.99 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +fr 2 270 01/12 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +fr 2 271 01/12 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +fr 2 272 01/12 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +fr 2 273 01/12 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +fr 2 274 01/12 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +fr 2 275 01/12 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +fr 2 276 01/12 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +fr 2 277 01/12 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +fr 2 278 01/12 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +fr 2 279 01/12 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +fr 2 280 01/12 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +fr 2 281 01/12 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +fr 2 282 01/12 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +fr 2 283 01/12 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +fr 2 284 01/12 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +fr 2 285 01/12 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +fr 2 286 01/12 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +fr 2 287 01/12 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +fr 2 288 01/12 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +fr 2 289 01/13 00:00 420000.0 420000.0 69.99 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +fr 2 290 01/13 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +fr 2 291 01/13 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +fr 2 292 01/13 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +fr 2 293 01/13 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +fr 2 294 01/13 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +fr 2 295 01/13 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +fr 2 296 01/13 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +fr 2 297 01/13 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +fr 2 298 01/13 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +fr 2 299 01/13 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +fr 2 300 01/13 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +fr 2 301 01/13 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +fr 2 302 01/13 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +fr 2 303 01/13 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +fr 2 304 01/13 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +fr 2 305 01/13 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +fr 2 306 01/13 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +fr 2 307 01/13 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +fr 2 308 01/13 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +fr 2 309 01/13 20:00 560000.0 560000.0 79.99 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +fr 2 310 01/13 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +fr 2 311 01/13 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +fr 2 312 01/13 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +fr 2 313 01/14 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +fr 2 314 01/14 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +fr 2 315 01/14 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +fr 2 316 01/14 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +fr 2 317 01/14 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +fr 2 318 01/14 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +fr 2 319 01/14 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +fr 2 320 01/14 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +fr 2 321 01/14 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +fr 2 322 01/14 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +fr 2 323 01/14 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +fr 2 324 01/14 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +fr 2 325 01/14 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +fr 2 326 01/14 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +fr 2 327 01/14 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +fr 2 328 01/14 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +fr 2 329 01/14 16:00 720000.0 720000.0 89.99 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +fr 2 330 01/14 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +fr 2 331 01/14 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +fr 2 332 01/14 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +fr 2 333 01/14 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +fr 2 334 01/14 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +fr 2 335 01/14 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +fr 2 336 01/14 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 +it 2 1 01/01 00:00 0.0 0.0 10.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +it 2 2 01/01 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +it 2 3 01/01 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +it 2 4 01/01 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +it 2 5 01/01 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +it 2 6 01/01 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +it 2 7 01/01 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +it 2 8 01/01 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +it 2 9 01/01 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +it 2 10 01/01 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +it 2 11 01/01 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +it 2 12 01/01 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +it 2 13 01/01 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +it 2 14 01/01 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +it 2 15 01/01 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +it 2 16 01/01 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +it 2 17 01/01 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +it 2 18 01/01 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +it 2 19 01/01 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +it 2 20 01/01 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +it 2 21 01/01 20:00 20000.0 20000.0 20.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +it 2 22 01/01 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +it 2 23 01/01 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +it 2 24 01/01 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +it 2 25 01/02 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +it 2 26 01/02 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +it 2 27 01/02 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +it 2 28 01/02 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +it 2 29 01/02 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +it 2 30 01/02 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +it 2 31 01/02 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +it 2 32 01/02 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +it 2 33 01/02 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +it 2 34 01/02 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +it 2 35 01/02 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +it 2 36 01/02 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +it 2 37 01/02 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +it 2 38 01/02 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +it 2 39 01/02 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +it 2 40 01/02 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +it 2 41 01/02 16:00 60000.0 60000.0 30.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +it 2 42 01/02 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +it 2 43 01/02 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +it 2 44 01/02 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +it 2 45 01/02 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +it 2 46 01/02 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +it 2 47 01/02 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +it 2 48 01/02 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +it 2 49 01/03 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +it 2 50 01/03 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +it 2 51 01/03 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +it 2 52 01/03 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +it 2 53 01/03 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +it 2 54 01/03 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +it 2 55 01/03 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +it 2 56 01/03 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +it 2 57 01/03 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +it 2 58 01/03 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +it 2 59 01/03 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +it 2 60 01/03 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +it 2 61 01/03 12:00 120000.0 120000.0 40.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +it 2 62 01/03 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +it 2 63 01/03 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +it 2 64 01/03 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +it 2 65 01/03 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +it 2 66 01/03 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +it 2 67 01/03 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +it 2 68 01/03 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +it 2 69 01/03 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +it 2 70 01/03 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +it 2 71 01/03 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +it 2 72 01/03 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +it 2 73 01/04 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +it 2 74 01/04 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +it 2 75 01/04 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +it 2 76 01/04 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +it 2 77 01/04 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +it 2 78 01/04 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +it 2 79 01/04 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +it 2 80 01/04 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +it 2 81 01/04 08:00 200000.0 200000.0 50.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +it 2 82 01/04 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +it 2 83 01/04 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +it 2 84 01/04 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +it 2 85 01/04 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +it 2 86 01/04 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +it 2 87 01/04 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +it 2 88 01/04 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +it 2 89 01/04 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +it 2 90 01/04 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +it 2 91 01/04 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +it 2 92 01/04 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +it 2 93 01/04 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +it 2 94 01/04 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +it 2 95 01/04 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +it 2 96 01/04 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +it 2 97 01/05 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +it 2 98 01/05 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +it 2 99 01/05 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +it 2 100 01/05 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +it 2 101 01/05 04:00 300000.0 300000.0 60.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +it 2 102 01/05 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +it 2 103 01/05 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +it 2 104 01/05 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +it 2 105 01/05 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +it 2 106 01/05 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +it 2 107 01/05 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +it 2 108 01/05 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +it 2 109 01/05 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +it 2 110 01/05 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +it 2 111 01/05 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +it 2 112 01/05 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +it 2 113 01/05 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +it 2 114 01/05 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +it 2 115 01/05 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +it 2 116 01/05 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +it 2 117 01/05 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +it 2 118 01/05 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +it 2 119 01/05 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +it 2 120 01/05 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +it 2 121 01/06 00:00 420000.0 420000.0 70.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +it 2 122 01/06 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +it 2 123 01/06 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +it 2 124 01/06 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +it 2 125 01/06 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +it 2 126 01/06 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +it 2 127 01/06 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +it 2 128 01/06 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +it 2 129 01/06 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +it 2 130 01/06 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +it 2 131 01/06 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +it 2 132 01/06 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +it 2 133 01/06 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +it 2 134 01/06 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +it 2 135 01/06 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +it 2 136 01/06 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +it 2 137 01/06 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +it 2 138 01/06 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +it 2 139 01/06 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +it 2 140 01/06 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +it 2 141 01/06 20:00 560000.0 560000.0 80.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +it 2 142 01/06 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +it 2 143 01/06 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +it 2 144 01/06 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +it 2 145 01/07 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +it 2 146 01/07 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +it 2 147 01/07 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +it 2 148 01/07 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +it 2 149 01/07 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +it 2 150 01/07 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +it 2 151 01/07 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +it 2 152 01/07 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +it 2 153 01/07 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +it 2 154 01/07 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +it 2 155 01/07 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +it 2 156 01/07 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +it 2 157 01/07 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +it 2 158 01/07 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +it 2 159 01/07 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +it 2 160 01/07 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +it 2 161 01/07 16:00 720000.0 720000.0 90.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +it 2 162 01/07 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +it 2 163 01/07 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +it 2 164 01/07 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +it 2 165 01/07 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +it 2 166 01/07 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +it 2 167 01/07 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +it 2 168 01/07 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 +it 2 169 01/08 00:00 0.0 0.0 10.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +it 2 170 01/08 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +it 2 171 01/08 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +it 2 172 01/08 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +it 2 173 01/08 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +it 2 174 01/08 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +it 2 175 01/08 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +it 2 176 01/08 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +it 2 177 01/08 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +it 2 178 01/08 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +it 2 179 01/08 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +it 2 180 01/08 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +it 2 181 01/08 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +it 2 182 01/08 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +it 2 183 01/08 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +it 2 184 01/08 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +it 2 185 01/08 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +it 2 186 01/08 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +it 2 187 01/08 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +it 2 188 01/08 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +it 2 189 01/08 20:00 20000.0 20000.0 20.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +it 2 190 01/08 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +it 2 191 01/08 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +it 2 192 01/08 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +it 2 193 01/09 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +it 2 194 01/09 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +it 2 195 01/09 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +it 2 196 01/09 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +it 2 197 01/09 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +it 2 198 01/09 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +it 2 199 01/09 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +it 2 200 01/09 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +it 2 201 01/09 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +it 2 202 01/09 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +it 2 203 01/09 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +it 2 204 01/09 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +it 2 205 01/09 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +it 2 206 01/09 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +it 2 207 01/09 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +it 2 208 01/09 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +it 2 209 01/09 16:00 60000.0 60000.0 30.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +it 2 210 01/09 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +it 2 211 01/09 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +it 2 212 01/09 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +it 2 213 01/09 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +it 2 214 01/09 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +it 2 215 01/09 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +it 2 216 01/09 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +it 2 217 01/10 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +it 2 218 01/10 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +it 2 219 01/10 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +it 2 220 01/10 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +it 2 221 01/10 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +it 2 222 01/10 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +it 2 223 01/10 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +it 2 224 01/10 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +it 2 225 01/10 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +it 2 226 01/10 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +it 2 227 01/10 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +it 2 228 01/10 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +it 2 229 01/10 12:00 120000.0 120000.0 40.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +it 2 230 01/10 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +it 2 231 01/10 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +it 2 232 01/10 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +it 2 233 01/10 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +it 2 234 01/10 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +it 2 235 01/10 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +it 2 236 01/10 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +it 2 237 01/10 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +it 2 238 01/10 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +it 2 239 01/10 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +it 2 240 01/10 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +it 2 241 01/11 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +it 2 242 01/11 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +it 2 243 01/11 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +it 2 244 01/11 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +it 2 245 01/11 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +it 2 246 01/11 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +it 2 247 01/11 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +it 2 248 01/11 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +it 2 249 01/11 08:00 200000.0 200000.0 50.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +it 2 250 01/11 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +it 2 251 01/11 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +it 2 252 01/11 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +it 2 253 01/11 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +it 2 254 01/11 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +it 2 255 01/11 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +it 2 256 01/11 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +it 2 257 01/11 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +it 2 258 01/11 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +it 2 259 01/11 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +it 2 260 01/11 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +it 2 261 01/11 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +it 2 262 01/11 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +it 2 263 01/11 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +it 2 264 01/11 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +it 2 265 01/12 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +it 2 266 01/12 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +it 2 267 01/12 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +it 2 268 01/12 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +it 2 269 01/12 04:00 300000.0 300000.0 60.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +it 2 270 01/12 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +it 2 271 01/12 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +it 2 272 01/12 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +it 2 273 01/12 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +it 2 274 01/12 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +it 2 275 01/12 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +it 2 276 01/12 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +it 2 277 01/12 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +it 2 278 01/12 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +it 2 279 01/12 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +it 2 280 01/12 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +it 2 281 01/12 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +it 2 282 01/12 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +it 2 283 01/12 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +it 2 284 01/12 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +it 2 285 01/12 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +it 2 286 01/12 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +it 2 287 01/12 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +it 2 288 01/12 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +it 2 289 01/13 00:00 420000.0 420000.0 70.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +it 2 290 01/13 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +it 2 291 01/13 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +it 2 292 01/13 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +it 2 293 01/13 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +it 2 294 01/13 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +it 2 295 01/13 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +it 2 296 01/13 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +it 2 297 01/13 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +it 2 298 01/13 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +it 2 299 01/13 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +it 2 300 01/13 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +it 2 301 01/13 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +it 2 302 01/13 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +it 2 303 01/13 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +it 2 304 01/13 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +it 2 305 01/13 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +it 2 306 01/13 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +it 2 307 01/13 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +it 2 308 01/13 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +it 2 309 01/13 20:00 560000.0 560000.0 80.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +it 2 310 01/13 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +it 2 311 01/13 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +it 2 312 01/13 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +it 2 313 01/14 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +it 2 314 01/14 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +it 2 315 01/14 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +it 2 316 01/14 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +it 2 317 01/14 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +it 2 318 01/14 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +it 2 319 01/14 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +it 2 320 01/14 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +it 2 321 01/14 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +it 2 322 01/14 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +it 2 323 01/14 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +it 2 324 01/14 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +it 2 325 01/14 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +it 2 326 01/14 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +it 2 327 01/14 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +it 2 328 01/14 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +it 2 329 01/14 16:00 720000.0 720000.0 90.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +it 2 330 01/14 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +it 2 331 01/14 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +it 2 332 01/14 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +it 2 333 01/14 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +it 2 334 01/14 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +it 2 335 01/14 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +it 2 336 01/14 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 diff --git a/tests/integration/raw_studies_blueprint/assets/aggregate_areas_raw_data/test-02.result.tsv b/tests/integration/raw_studies_blueprint/assets/aggregate_areas_raw_data/test-02.result.tsv new file mode 100644 index 0000000000..6d63782e81 --- /dev/null +++ b/tests/integration/raw_studies_blueprint/assets/aggregate_areas_raw_data/test-02.result.tsv @@ -0,0 +1,1009 @@ +area mcYear timeId time 01_SOLAR MWH 02_WIND_ON MWH 03_WIND_OFF MWH 04_RES MWH 05_NUCLEAR MWH 06_COAL MWH 07_GAS MWH 08_NON-RES MWH 09_HYDRO_PUMP MWH 01_SOLAR NP COST - EURO 02_WIND_ON NP COST - EURO 03_WIND_OFF NP COST - EURO 04_RES NP COST - EURO 05_NUCLEAR NP COST - EURO 06_COAL NP COST - EURO 07_GAS NP COST - EURO 08_NON-RES NP COST - EURO 09_HYDRO_PUMP NP COST - EURO 01_SOLAR NODU 02_WIND_ON NODU 03_WIND_OFF NODU 04_RES NODU 05_NUCLEAR NODU 06_COAL NODU 07_GAS NODU 08_NON-RES NODU 09_HYDRO_PUMP NODU +de 1 1 01/01 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 2 01/01 01:00 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 3 01/01 02:00 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 4 01/01 03:00 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 5 01/01 04:00 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 6 01/01 05:00 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 7 01/01 06:00 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 8 01/01 07:00 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 9 01/01 08:00 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 10 01/01 09:00 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 11 01/01 10:00 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 12 01/01 11:00 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 13 01/01 12:00 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 14 01/01 13:00 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 15 01/01 14:00 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 16 01/01 15:00 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 17 01/01 16:00 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 18 01/01 17:00 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 19 01/01 18:00 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 20 01/01 19:00 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 21 01/01 20:00 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 22 01/01 21:00 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 23 01/01 22:00 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 24 01/01 23:00 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 25 01/02 00:00 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 26 01/02 01:00 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 27 01/02 02:00 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 28 01/02 03:00 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 29 01/02 04:00 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 30 01/02 05:00 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 31 01/02 06:00 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 32 01/02 07:00 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 33 01/02 08:00 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 34 01/02 09:00 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 35 01/02 10:00 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 36 01/02 11:00 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 37 01/02 12:00 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 38 01/02 13:00 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 39 01/02 14:00 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 40 01/02 15:00 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 41 01/02 16:00 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 42 01/02 17:00 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 43 01/02 18:00 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 44 01/02 19:00 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 45 01/02 20:00 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 46 01/02 21:00 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 47 01/02 22:00 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 48 01/02 23:00 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 49 01/03 00:00 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 50 01/03 01:00 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 51 01/03 02:00 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 52 01/03 03:00 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 53 01/03 04:00 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 54 01/03 05:00 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 55 01/03 06:00 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 56 01/03 07:00 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 57 01/03 08:00 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 58 01/03 09:00 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 59 01/03 10:00 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 60 01/03 11:00 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 61 01/03 12:00 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 62 01/03 13:00 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 63 01/03 14:00 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 64 01/03 15:00 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 65 01/03 16:00 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 66 01/03 17:00 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 67 01/03 18:00 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 68 01/03 19:00 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 69 01/03 20:00 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 70 01/03 21:00 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 71 01/03 22:00 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 72 01/03 23:00 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 73 01/04 00:00 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 74 01/04 01:00 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 75 01/04 02:00 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 76 01/04 03:00 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 77 01/04 04:00 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 78 01/04 05:00 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 79 01/04 06:00 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 80 01/04 07:00 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 81 01/04 08:00 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 82 01/04 09:00 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 83 01/04 10:00 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 84 01/04 11:00 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 85 01/04 12:00 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 86 01/04 13:00 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 87 01/04 14:00 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 88 01/04 15:00 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 89 01/04 16:00 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 90 01/04 17:00 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 91 01/04 18:00 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 92 01/04 19:00 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 93 01/04 20:00 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 94 01/04 21:00 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 95 01/04 22:00 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 96 01/04 23:00 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 97 01/05 00:00 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 98 01/05 01:00 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 99 01/05 02:00 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 100 01/05 03:00 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 101 01/05 04:00 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 102 01/05 05:00 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 103 01/05 06:00 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 104 01/05 07:00 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 105 01/05 08:00 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 106 01/05 09:00 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 107 01/05 10:00 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 108 01/05 11:00 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 109 01/05 12:00 2000.0 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 110 01/05 13:00 2000.0 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 111 01/05 14:00 2000.0 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 112 01/05 15:00 2000.0 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 113 01/05 16:00 2000.0 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 114 01/05 17:00 2000.0 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 115 01/05 18:00 2000.0 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 116 01/05 19:00 2000.0 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 117 01/05 20:00 2000.0 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 118 01/05 21:00 2000.0 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 119 01/05 22:00 2000.0 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 120 01/05 23:00 2000.0 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 121 01/06 00:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 122 01/06 01:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 123 01/06 02:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 124 01/06 03:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 125 01/06 04:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 126 01/06 05:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 127 01/06 06:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 128 01/06 07:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 129 01/06 08:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 130 01/06 09:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 131 01/06 10:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 132 01/06 11:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 133 01/06 12:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 134 01/06 13:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 135 01/06 14:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 136 01/06 15:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 137 01/06 16:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 138 01/06 17:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 139 01/06 18:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 140 01/06 19:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 141 01/06 20:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 142 01/06 21:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 143 01/06 22:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 144 01/06 23:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 145 01/07 00:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 146 01/07 01:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 147 01/07 02:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 148 01/07 03:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 149 01/07 04:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 150 01/07 05:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 151 01/07 06:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 152 01/07 07:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 153 01/07 08:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 154 01/07 09:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 155 01/07 10:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 156 01/07 11:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 157 01/07 12:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 158 01/07 13:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 159 01/07 14:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 160 01/07 15:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 161 01/07 16:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 162 01/07 17:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +de 1 163 01/07 18:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +de 1 164 01/07 19:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +de 1 165 01/07 20:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +de 1 166 01/07 21:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +de 1 167 01/07 22:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +de 1 168 01/07 23:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +de 1 169 01/08 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 170 01/08 01:00 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 171 01/08 02:00 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 172 01/08 03:00 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 173 01/08 04:00 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 174 01/08 05:00 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 175 01/08 06:00 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 176 01/08 07:00 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 177 01/08 08:00 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 178 01/08 09:00 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 179 01/08 10:00 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 180 01/08 11:00 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 181 01/08 12:00 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 182 01/08 13:00 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 183 01/08 14:00 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 184 01/08 15:00 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 185 01/08 16:00 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 186 01/08 17:00 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 187 01/08 18:00 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 188 01/08 19:00 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 189 01/08 20:00 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 190 01/08 21:00 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 191 01/08 22:00 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 192 01/08 23:00 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 193 01/09 00:00 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 194 01/09 01:00 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 195 01/09 02:00 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 196 01/09 03:00 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 197 01/09 04:00 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 198 01/09 05:00 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 199 01/09 06:00 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 200 01/09 07:00 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 201 01/09 08:00 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 202 01/09 09:00 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 203 01/09 10:00 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 204 01/09 11:00 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 205 01/09 12:00 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 206 01/09 13:00 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 207 01/09 14:00 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 208 01/09 15:00 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 209 01/09 16:00 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 210 01/09 17:00 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 211 01/09 18:00 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 212 01/09 19:00 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 213 01/09 20:00 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 214 01/09 21:00 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 215 01/09 22:00 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 216 01/09 23:00 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 217 01/10 00:00 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 218 01/10 01:00 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 219 01/10 02:00 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 220 01/10 03:00 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 221 01/10 04:00 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 222 01/10 05:00 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 223 01/10 06:00 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 224 01/10 07:00 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 225 01/10 08:00 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 226 01/10 09:00 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 227 01/10 10:00 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 228 01/10 11:00 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 229 01/10 12:00 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +de 1 230 01/10 13:00 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 231 01/10 14:00 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 232 01/10 15:00 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 233 01/10 16:00 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 234 01/10 17:00 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 235 01/10 18:00 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 236 01/10 19:00 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 237 01/10 20:00 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 238 01/10 21:00 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 239 01/10 22:00 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 240 01/10 23:00 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 241 01/11 00:00 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 242 01/11 01:00 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 243 01/11 02:00 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 244 01/11 03:00 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 245 01/11 04:00 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 246 01/11 05:00 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 247 01/11 06:00 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 248 01/11 07:00 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 249 01/11 08:00 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +de 1 250 01/11 09:00 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 251 01/11 10:00 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 252 01/11 11:00 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 253 01/11 12:00 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 254 01/11 13:00 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 255 01/11 14:00 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 256 01/11 15:00 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 257 01/11 16:00 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 258 01/11 17:00 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 259 01/11 18:00 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 260 01/11 19:00 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 261 01/11 20:00 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 262 01/11 21:00 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 263 01/11 22:00 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 264 01/11 23:00 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 265 01/12 00:00 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 266 01/12 01:00 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 267 01/12 02:00 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 268 01/12 03:00 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 269 01/12 04:00 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +de 1 270 01/12 05:00 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 271 01/12 06:00 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 272 01/12 07:00 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 273 01/12 08:00 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 274 01/12 09:00 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 275 01/12 10:00 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 276 01/12 11:00 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 277 01/12 12:00 2000.0 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 278 01/12 13:00 2000.0 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 279 01/12 14:00 2000.0 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 280 01/12 15:00 2000.0 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 281 01/12 16:00 2000.0 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 282 01/12 17:00 2000.0 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 283 01/12 18:00 2000.0 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 284 01/12 19:00 2000.0 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 285 01/12 20:00 2000.0 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 286 01/12 21:00 2000.0 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 287 01/12 22:00 2000.0 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 288 01/12 23:00 2000.0 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 289 01/13 00:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +de 1 290 01/13 01:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 291 01/13 02:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 292 01/13 03:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 293 01/13 04:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 294 01/13 05:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 295 01/13 06:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 296 01/13 07:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 297 01/13 08:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 298 01/13 09:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 299 01/13 10:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 300 01/13 11:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 301 01/13 12:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 302 01/13 13:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 303 01/13 14:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 304 01/13 15:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 305 01/13 16:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 306 01/13 17:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 307 01/13 18:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 308 01/13 19:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 309 01/13 20:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +de 1 310 01/13 21:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 311 01/13 22:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 312 01/13 23:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 313 01/14 00:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 314 01/14 01:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 315 01/14 02:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 316 01/14 03:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 317 01/14 04:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 318 01/14 05:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 319 01/14 06:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 320 01/14 07:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 321 01/14 08:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 322 01/14 09:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 323 01/14 10:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 324 01/14 11:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 325 01/14 12:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 326 01/14 13:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 327 01/14 14:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 328 01/14 15:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 329 01/14 16:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +de 1 330 01/14 17:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +de 1 331 01/14 18:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +de 1 332 01/14 19:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +de 1 333 01/14 20:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +de 1 334 01/14 21:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +de 1 335 01/14 22:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +de 1 336 01/14 23:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +fr 1 1 01/01 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 2 01/01 01:00 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 3 01/01 02:00 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 4 01/01 03:00 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 5 01/01 04:00 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 6 01/01 05:00 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 7 01/01 06:00 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 8 01/01 07:00 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 9 01/01 08:00 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 10 01/01 09:00 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 11 01/01 10:00 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 12 01/01 11:00 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 13 01/01 12:00 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 14 01/01 13:00 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 15 01/01 14:00 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 16 01/01 15:00 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 17 01/01 16:00 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 18 01/01 17:00 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 19 01/01 18:00 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 20 01/01 19:00 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 21 01/01 20:00 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 22 01/01 21:00 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 23 01/01 22:00 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 24 01/01 23:00 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 25 01/02 00:00 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 26 01/02 01:00 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 27 01/02 02:00 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 28 01/02 03:00 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 29 01/02 04:00 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 30 01/02 05:00 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 31 01/02 06:00 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 32 01/02 07:00 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 33 01/02 08:00 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 34 01/02 09:00 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 35 01/02 10:00 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 36 01/02 11:00 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 37 01/02 12:00 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 38 01/02 13:00 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 39 01/02 14:00 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 40 01/02 15:00 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 41 01/02 16:00 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 42 01/02 17:00 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 43 01/02 18:00 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 44 01/02 19:00 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 45 01/02 20:00 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 46 01/02 21:00 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 47 01/02 22:00 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 48 01/02 23:00 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 49 01/03 00:00 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 50 01/03 01:00 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 51 01/03 02:00 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 52 01/03 03:00 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 53 01/03 04:00 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 54 01/03 05:00 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 55 01/03 06:00 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 56 01/03 07:00 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 57 01/03 08:00 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 58 01/03 09:00 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 59 01/03 10:00 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 60 01/03 11:00 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 61 01/03 12:00 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 62 01/03 13:00 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 63 01/03 14:00 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 64 01/03 15:00 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 65 01/03 16:00 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 66 01/03 17:00 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 67 01/03 18:00 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 68 01/03 19:00 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 69 01/03 20:00 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 70 01/03 21:00 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 71 01/03 22:00 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 72 01/03 23:00 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 73 01/04 00:00 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 74 01/04 01:00 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 75 01/04 02:00 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 76 01/04 03:00 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 77 01/04 04:00 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 78 01/04 05:00 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 79 01/04 06:00 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 80 01/04 07:00 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 81 01/04 08:00 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 82 01/04 09:00 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 83 01/04 10:00 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 84 01/04 11:00 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 85 01/04 12:00 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 86 01/04 13:00 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 87 01/04 14:00 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 88 01/04 15:00 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 89 01/04 16:00 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 90 01/04 17:00 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 91 01/04 18:00 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 92 01/04 19:00 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 93 01/04 20:00 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 94 01/04 21:00 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 95 01/04 22:00 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 96 01/04 23:00 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 97 01/05 00:00 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 98 01/05 01:00 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 99 01/05 02:00 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 100 01/05 03:00 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 101 01/05 04:00 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 102 01/05 05:00 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 103 01/05 06:00 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 104 01/05 07:00 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 105 01/05 08:00 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 106 01/05 09:00 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 107 01/05 10:00 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 108 01/05 11:00 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 109 01/05 12:00 2000.0 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 110 01/05 13:00 2000.0 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 111 01/05 14:00 2000.0 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 112 01/05 15:00 2000.0 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 113 01/05 16:00 2000.0 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 114 01/05 17:00 2000.0 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 115 01/05 18:00 2000.0 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 116 01/05 19:00 2000.0 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 117 01/05 20:00 2000.0 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 118 01/05 21:00 2000.0 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 119 01/05 22:00 2000.0 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 120 01/05 23:00 2000.0 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 121 01/06 00:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 122 01/06 01:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 123 01/06 02:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 124 01/06 03:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 125 01/06 04:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 126 01/06 05:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 127 01/06 06:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 128 01/06 07:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 129 01/06 08:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 130 01/06 09:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 131 01/06 10:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 132 01/06 11:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 133 01/06 12:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 134 01/06 13:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 135 01/06 14:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 136 01/06 15:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 137 01/06 16:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 138 01/06 17:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 139 01/06 18:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 140 01/06 19:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 141 01/06 20:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 142 01/06 21:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 143 01/06 22:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 144 01/06 23:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 145 01/07 00:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 146 01/07 01:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 147 01/07 02:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 148 01/07 03:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 149 01/07 04:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 150 01/07 05:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 151 01/07 06:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 152 01/07 07:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 153 01/07 08:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 154 01/07 09:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 155 01/07 10:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 156 01/07 11:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 157 01/07 12:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 158 01/07 13:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 159 01/07 14:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 160 01/07 15:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 161 01/07 16:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 162 01/07 17:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +fr 1 163 01/07 18:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +fr 1 164 01/07 19:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +fr 1 165 01/07 20:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +fr 1 166 01/07 21:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +fr 1 167 01/07 22:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +fr 1 168 01/07 23:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +fr 1 169 01/08 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 170 01/08 01:00 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 171 01/08 02:00 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 172 01/08 03:00 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 173 01/08 04:00 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 174 01/08 05:00 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 175 01/08 06:00 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 176 01/08 07:00 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 177 01/08 08:00 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 178 01/08 09:00 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 179 01/08 10:00 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 180 01/08 11:00 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 181 01/08 12:00 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 182 01/08 13:00 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 183 01/08 14:00 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 184 01/08 15:00 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 185 01/08 16:00 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 186 01/08 17:00 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 187 01/08 18:00 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 188 01/08 19:00 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 189 01/08 20:00 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 190 01/08 21:00 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 191 01/08 22:00 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 192 01/08 23:00 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 193 01/09 00:00 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 194 01/09 01:00 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 195 01/09 02:00 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 196 01/09 03:00 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 197 01/09 04:00 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 198 01/09 05:00 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 199 01/09 06:00 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 200 01/09 07:00 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 201 01/09 08:00 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 202 01/09 09:00 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 203 01/09 10:00 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 204 01/09 11:00 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 205 01/09 12:00 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 206 01/09 13:00 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 207 01/09 14:00 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 208 01/09 15:00 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 209 01/09 16:00 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 210 01/09 17:00 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 211 01/09 18:00 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 212 01/09 19:00 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 213 01/09 20:00 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 214 01/09 21:00 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 215 01/09 22:00 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 216 01/09 23:00 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 217 01/10 00:00 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 218 01/10 01:00 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 219 01/10 02:00 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 220 01/10 03:00 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 221 01/10 04:00 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 222 01/10 05:00 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 223 01/10 06:00 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 224 01/10 07:00 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 225 01/10 08:00 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 226 01/10 09:00 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 227 01/10 10:00 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 228 01/10 11:00 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 229 01/10 12:00 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr 1 230 01/10 13:00 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 231 01/10 14:00 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 232 01/10 15:00 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 233 01/10 16:00 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 234 01/10 17:00 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 235 01/10 18:00 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 236 01/10 19:00 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 237 01/10 20:00 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 238 01/10 21:00 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 239 01/10 22:00 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 240 01/10 23:00 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 241 01/11 00:00 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 242 01/11 01:00 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 243 01/11 02:00 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 244 01/11 03:00 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 245 01/11 04:00 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 246 01/11 05:00 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 247 01/11 06:00 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 248 01/11 07:00 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 249 01/11 08:00 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +fr 1 250 01/11 09:00 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 251 01/11 10:00 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 252 01/11 11:00 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 253 01/11 12:00 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 254 01/11 13:00 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 255 01/11 14:00 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 256 01/11 15:00 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 257 01/11 16:00 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 258 01/11 17:00 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 259 01/11 18:00 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 260 01/11 19:00 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 261 01/11 20:00 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 262 01/11 21:00 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 263 01/11 22:00 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 264 01/11 23:00 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 265 01/12 00:00 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 266 01/12 01:00 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 267 01/12 02:00 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 268 01/12 03:00 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 269 01/12 04:00 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +fr 1 270 01/12 05:00 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 271 01/12 06:00 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 272 01/12 07:00 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 273 01/12 08:00 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 274 01/12 09:00 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 275 01/12 10:00 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 276 01/12 11:00 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 277 01/12 12:00 2000.0 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 278 01/12 13:00 2000.0 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 279 01/12 14:00 2000.0 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 280 01/12 15:00 2000.0 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 281 01/12 16:00 2000.0 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 282 01/12 17:00 2000.0 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 283 01/12 18:00 2000.0 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 284 01/12 19:00 2000.0 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 285 01/12 20:00 2000.0 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 286 01/12 21:00 2000.0 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 287 01/12 22:00 2000.0 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 288 01/12 23:00 2000.0 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 289 01/13 00:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +fr 1 290 01/13 01:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 291 01/13 02:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 292 01/13 03:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 293 01/13 04:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 294 01/13 05:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 295 01/13 06:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 296 01/13 07:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 297 01/13 08:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 298 01/13 09:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 299 01/13 10:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 300 01/13 11:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 301 01/13 12:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 302 01/13 13:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 303 01/13 14:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 304 01/13 15:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 305 01/13 16:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 306 01/13 17:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 307 01/13 18:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 308 01/13 19:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 309 01/13 20:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +fr 1 310 01/13 21:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 311 01/13 22:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 312 01/13 23:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 313 01/14 00:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 314 01/14 01:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 315 01/14 02:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 316 01/14 03:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 317 01/14 04:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 318 01/14 05:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 319 01/14 06:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 320 01/14 07:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 321 01/14 08:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 322 01/14 09:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 323 01/14 10:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 324 01/14 11:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 325 01/14 12:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 326 01/14 13:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 327 01/14 14:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 328 01/14 15:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 329 01/14 16:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +fr 1 330 01/14 17:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +fr 1 331 01/14 18:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +fr 1 332 01/14 19:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +fr 1 333 01/14 20:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +fr 1 334 01/14 21:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +fr 1 335 01/14 22:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +fr 1 336 01/14 23:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +it 1 1 01/01 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 2 01/01 01:00 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 3 01/01 02:00 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 4 01/01 03:00 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 5 01/01 04:00 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 6 01/01 05:00 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 7 01/01 06:00 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 8 01/01 07:00 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 9 01/01 08:00 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 10 01/01 09:00 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 11 01/01 10:00 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 12 01/01 11:00 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 13 01/01 12:00 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 14 01/01 13:00 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 15 01/01 14:00 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 16 01/01 15:00 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 17 01/01 16:00 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 18 01/01 17:00 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 19 01/01 18:00 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 20 01/01 19:00 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 21 01/01 20:00 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 22 01/01 21:00 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 23 01/01 22:00 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 24 01/01 23:00 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 25 01/02 00:00 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 26 01/02 01:00 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 27 01/02 02:00 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 28 01/02 03:00 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 29 01/02 04:00 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 30 01/02 05:00 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 31 01/02 06:00 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 32 01/02 07:00 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 33 01/02 08:00 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 34 01/02 09:00 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 35 01/02 10:00 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 36 01/02 11:00 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 37 01/02 12:00 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 38 01/02 13:00 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 39 01/02 14:00 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 40 01/02 15:00 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 41 01/02 16:00 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 42 01/02 17:00 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 43 01/02 18:00 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 44 01/02 19:00 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 45 01/02 20:00 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 46 01/02 21:00 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 47 01/02 22:00 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 48 01/02 23:00 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 49 01/03 00:00 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 50 01/03 01:00 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 51 01/03 02:00 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 52 01/03 03:00 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 53 01/03 04:00 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 54 01/03 05:00 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 55 01/03 06:00 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 56 01/03 07:00 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 57 01/03 08:00 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 58 01/03 09:00 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 59 01/03 10:00 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 60 01/03 11:00 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 61 01/03 12:00 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 62 01/03 13:00 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 63 01/03 14:00 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 64 01/03 15:00 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 65 01/03 16:00 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 66 01/03 17:00 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 67 01/03 18:00 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 68 01/03 19:00 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 69 01/03 20:00 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 70 01/03 21:00 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 71 01/03 22:00 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 72 01/03 23:00 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 73 01/04 00:00 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 74 01/04 01:00 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 75 01/04 02:00 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 76 01/04 03:00 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 77 01/04 04:00 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 78 01/04 05:00 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 79 01/04 06:00 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 80 01/04 07:00 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 81 01/04 08:00 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 82 01/04 09:00 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 83 01/04 10:00 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 84 01/04 11:00 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 85 01/04 12:00 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 86 01/04 13:00 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 87 01/04 14:00 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 88 01/04 15:00 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 89 01/04 16:00 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 90 01/04 17:00 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 91 01/04 18:00 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 92 01/04 19:00 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 93 01/04 20:00 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 94 01/04 21:00 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 95 01/04 22:00 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 96 01/04 23:00 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 97 01/05 00:00 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 98 01/05 01:00 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 99 01/05 02:00 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 100 01/05 03:00 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 101 01/05 04:00 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 102 01/05 05:00 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 103 01/05 06:00 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 104 01/05 07:00 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 105 01/05 08:00 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 106 01/05 09:00 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 107 01/05 10:00 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 108 01/05 11:00 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 109 01/05 12:00 2000.0 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 110 01/05 13:00 2000.0 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 111 01/05 14:00 2000.0 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 112 01/05 15:00 2000.0 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 113 01/05 16:00 2000.0 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 114 01/05 17:00 2000.0 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 115 01/05 18:00 2000.0 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 116 01/05 19:00 2000.0 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 117 01/05 20:00 2000.0 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 118 01/05 21:00 2000.0 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 119 01/05 22:00 2000.0 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 120 01/05 23:00 2000.0 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 121 01/06 00:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 122 01/06 01:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 123 01/06 02:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 124 01/06 03:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 125 01/06 04:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 126 01/06 05:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 127 01/06 06:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 128 01/06 07:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 129 01/06 08:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 130 01/06 09:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 131 01/06 10:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 132 01/06 11:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 133 01/06 12:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 134 01/06 13:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 135 01/06 14:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 136 01/06 15:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 137 01/06 16:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 138 01/06 17:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 139 01/06 18:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 140 01/06 19:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 141 01/06 20:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 142 01/06 21:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 143 01/06 22:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 144 01/06 23:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 145 01/07 00:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 146 01/07 01:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 147 01/07 02:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 148 01/07 03:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 149 01/07 04:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 150 01/07 05:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 151 01/07 06:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 152 01/07 07:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 153 01/07 08:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 154 01/07 09:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 155 01/07 10:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 156 01/07 11:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 157 01/07 12:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 158 01/07 13:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 159 01/07 14:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 160 01/07 15:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 161 01/07 16:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 162 01/07 17:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +it 1 163 01/07 18:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +it 1 164 01/07 19:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +it 1 165 01/07 20:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +it 1 166 01/07 21:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +it 1 167 01/07 22:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +it 1 168 01/07 23:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +it 1 169 01/08 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 170 01/08 01:00 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 171 01/08 02:00 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 172 01/08 03:00 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 173 01/08 04:00 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 174 01/08 05:00 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 175 01/08 06:00 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 176 01/08 07:00 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 177 01/08 08:00 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 178 01/08 09:00 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 179 01/08 10:00 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 180 01/08 11:00 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 181 01/08 12:00 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 182 01/08 13:00 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 183 01/08 14:00 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 184 01/08 15:00 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 185 01/08 16:00 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 186 01/08 17:00 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 187 01/08 18:00 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 188 01/08 19:00 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 189 01/08 20:00 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 190 01/08 21:00 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 191 01/08 22:00 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 192 01/08 23:00 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 193 01/09 00:00 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 194 01/09 01:00 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 195 01/09 02:00 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 196 01/09 03:00 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 197 01/09 04:00 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 198 01/09 05:00 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 199 01/09 06:00 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 200 01/09 07:00 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 201 01/09 08:00 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 202 01/09 09:00 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 203 01/09 10:00 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 204 01/09 11:00 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 205 01/09 12:00 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 206 01/09 13:00 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 207 01/09 14:00 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 208 01/09 15:00 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 209 01/09 16:00 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 210 01/09 17:00 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 211 01/09 18:00 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 212 01/09 19:00 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 213 01/09 20:00 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 214 01/09 21:00 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 215 01/09 22:00 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 216 01/09 23:00 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 217 01/10 00:00 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 218 01/10 01:00 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 219 01/10 02:00 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 220 01/10 03:00 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 221 01/10 04:00 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 222 01/10 05:00 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 223 01/10 06:00 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 224 01/10 07:00 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 225 01/10 08:00 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 226 01/10 09:00 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 227 01/10 10:00 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 228 01/10 11:00 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 229 01/10 12:00 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 +it 1 230 01/10 13:00 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 231 01/10 14:00 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 232 01/10 15:00 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 233 01/10 16:00 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 234 01/10 17:00 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 235 01/10 18:00 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 236 01/10 19:00 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 237 01/10 20:00 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 238 01/10 21:00 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 239 01/10 22:00 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 240 01/10 23:00 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 241 01/11 00:00 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 242 01/11 01:00 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 243 01/11 02:00 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 244 01/11 03:00 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 245 01/11 04:00 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 246 01/11 05:00 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 247 01/11 06:00 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 248 01/11 07:00 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 249 01/11 08:00 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 +it 1 250 01/11 09:00 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 251 01/11 10:00 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 252 01/11 11:00 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 253 01/11 12:00 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 254 01/11 13:00 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 255 01/11 14:00 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 256 01/11 15:00 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 257 01/11 16:00 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 258 01/11 17:00 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 259 01/11 18:00 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 260 01/11 19:00 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 261 01/11 20:00 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 262 01/11 21:00 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 263 01/11 22:00 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 264 01/11 23:00 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 265 01/12 00:00 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 266 01/12 01:00 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 267 01/12 02:00 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 268 01/12 03:00 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 269 01/12 04:00 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 +it 1 270 01/12 05:00 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 271 01/12 06:00 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 272 01/12 07:00 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 273 01/12 08:00 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 274 01/12 09:00 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 275 01/12 10:00 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 276 01/12 11:00 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 277 01/12 12:00 2000.0 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 278 01/12 13:00 2000.0 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 279 01/12 14:00 2000.0 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 280 01/12 15:00 2000.0 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 281 01/12 16:00 2000.0 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 282 01/12 17:00 2000.0 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 283 01/12 18:00 2000.0 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 284 01/12 19:00 2000.0 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 285 01/12 20:00 2000.0 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 286 01/12 21:00 2000.0 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 287 01/12 22:00 2000.0 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 288 01/12 23:00 2000.0 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 289 01/13 00:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 +it 1 290 01/13 01:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 291 01/13 02:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 292 01/13 03:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 293 01/13 04:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 294 01/13 05:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 295 01/13 06:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 296 01/13 07:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 297 01/13 08:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 298 01/13 09:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 299 01/13 10:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 300 01/13 11:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 301 01/13 12:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 302 01/13 13:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 303 01/13 14:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 304 01/13 15:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 305 01/13 16:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 306 01/13 17:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 307 01/13 18:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 308 01/13 19:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 309 01/13 20:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 +it 1 310 01/13 21:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 311 01/13 22:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 312 01/13 23:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 313 01/14 00:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 314 01/14 01:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 315 01/14 02:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 316 01/14 03:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 317 01/14 04:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 318 01/14 05:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 319 01/14 06:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 320 01/14 07:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 321 01/14 08:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 322 01/14 09:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 323 01/14 10:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 324 01/14 11:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 325 01/14 12:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 326 01/14 13:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 327 01/14 14:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 328 01/14 15:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 329 01/14 16:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 +it 1 330 01/14 17:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +it 1 331 01/14 18:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +it 1 332 01/14 19:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +it 1 333 01/14 20:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +it 1 334 01/14 21:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +it 1 335 01/14 22:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 +it 1 336 01/14 23:00 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 2000.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 diff --git a/tests/integration/raw_studies_blueprint/assets/aggregate_areas_raw_data/test-03.result.tsv b/tests/integration/raw_studies_blueprint/assets/aggregate_areas_raw_data/test-03.result.tsv new file mode 100644 index 0000000000..70d4e31c84 --- /dev/null +++ b/tests/integration/raw_studies_blueprint/assets/aggregate_areas_raw_data/test-03.result.tsv @@ -0,0 +1,9 @@ +area mcYear timeId time OP. COST MRG. PRICE +de 1 1 1 46452000.0 47.14 +de 1 2 2 46452000.0 47.14 +es 1 1 1 46452000.0 47.14 +es 1 2 2 46452000.0 47.14 +de 2 1 1 46452000.0 47.14 +de 2 2 2 46452000.0 47.14 +es 2 1 1 46452000.0 47.14 +es 2 2 2 46452000.0 47.14 diff --git a/tests/integration/raw_studies_blueprint/assets/aggregate_areas_raw_data/test-04.result.tsv b/tests/integration/raw_studies_blueprint/assets/aggregate_areas_raw_data/test-04.result.tsv new file mode 100644 index 0000000000..aef0763263 --- /dev/null +++ b/tests/integration/raw_studies_blueprint/assets/aggregate_areas_raw_data/test-04.result.tsv @@ -0,0 +1,1009 @@ +area mcYear timeId time OV. COST OP. COST MRG. PRICE CO2 EMIS. BALANCE ROW BAL. PSP MISC. NDG LOAD H. ROR WIND SOLAR NUCLEAR LIGNITE COAL GAS OIL MIX. FUEL MISC. DTG H. STOR H. PUMP H. LEV H. INFL H. OVFL H. VAL H. COST UNSP. ENRG SPIL. ENRG LOLD LOLP AVL DTG DTG MRG MAX MRG NP COST NODU +de 2 1 01/01 00:00 0.0 0.0 9.98 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +de 2 2 01/01 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +de 2 3 01/01 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +de 2 4 01/01 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +de 2 5 01/01 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +de 2 6 01/01 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +de 2 7 01/01 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +de 2 8 01/01 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +de 2 9 01/01 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +de 2 10 01/01 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +de 2 11 01/01 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +de 2 12 01/01 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +de 2 13 01/01 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +de 2 14 01/01 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +de 2 15 01/01 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +de 2 16 01/01 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +de 2 17 01/01 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +de 2 18 01/01 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +de 2 19 01/01 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +de 2 20 01/01 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +de 2 21 01/01 20:00 20000.0 20000.0 19.98 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +de 2 22 01/01 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +de 2 23 01/01 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +de 2 24 01/01 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +de 2 25 01/02 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +de 2 26 01/02 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +de 2 27 01/02 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +de 2 28 01/02 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +de 2 29 01/02 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +de 2 30 01/02 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +de 2 31 01/02 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +de 2 32 01/02 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +de 2 33 01/02 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +de 2 34 01/02 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +de 2 35 01/02 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +de 2 36 01/02 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +de 2 37 01/02 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +de 2 38 01/02 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +de 2 39 01/02 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +de 2 40 01/02 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +de 2 41 01/02 16:00 60000.0 60000.0 29.98 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +de 2 42 01/02 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +de 2 43 01/02 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +de 2 44 01/02 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +de 2 45 01/02 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +de 2 46 01/02 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +de 2 47 01/02 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +de 2 48 01/02 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +de 2 49 01/03 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +de 2 50 01/03 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +de 2 51 01/03 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +de 2 52 01/03 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +de 2 53 01/03 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +de 2 54 01/03 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +de 2 55 01/03 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +de 2 56 01/03 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +de 2 57 01/03 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +de 2 58 01/03 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +de 2 59 01/03 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +de 2 60 01/03 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +de 2 61 01/03 12:00 120000.0 120000.0 39.98 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +de 2 62 01/03 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +de 2 63 01/03 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +de 2 64 01/03 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +de 2 65 01/03 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +de 2 66 01/03 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +de 2 67 01/03 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +de 2 68 01/03 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +de 2 69 01/03 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +de 2 70 01/03 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +de 2 71 01/03 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +de 2 72 01/03 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +de 2 73 01/04 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +de 2 74 01/04 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +de 2 75 01/04 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +de 2 76 01/04 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +de 2 77 01/04 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +de 2 78 01/04 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +de 2 79 01/04 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +de 2 80 01/04 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +de 2 81 01/04 08:00 200000.0 200000.0 49.98 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +de 2 82 01/04 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +de 2 83 01/04 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +de 2 84 01/04 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +de 2 85 01/04 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +de 2 86 01/04 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +de 2 87 01/04 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +de 2 88 01/04 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +de 2 89 01/04 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +de 2 90 01/04 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +de 2 91 01/04 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +de 2 92 01/04 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +de 2 93 01/04 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +de 2 94 01/04 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +de 2 95 01/04 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +de 2 96 01/04 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +de 2 97 01/05 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +de 2 98 01/05 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +de 2 99 01/05 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +de 2 100 01/05 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +de 2 101 01/05 04:00 300000.0 300000.0 59.98 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +de 2 102 01/05 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +de 2 103 01/05 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +de 2 104 01/05 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +de 2 105 01/05 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +de 2 106 01/05 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +de 2 107 01/05 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +de 2 108 01/05 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +de 2 109 01/05 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +de 2 110 01/05 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +de 2 111 01/05 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +de 2 112 01/05 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +de 2 113 01/05 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +de 2 114 01/05 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +de 2 115 01/05 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +de 2 116 01/05 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +de 2 117 01/05 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +de 2 118 01/05 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +de 2 119 01/05 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +de 2 120 01/05 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +de 2 121 01/06 00:00 420000.0 420000.0 69.98 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +de 2 122 01/06 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +de 2 123 01/06 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +de 2 124 01/06 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +de 2 125 01/06 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +de 2 126 01/06 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +de 2 127 01/06 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +de 2 128 01/06 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +de 2 129 01/06 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +de 2 130 01/06 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +de 2 131 01/06 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +de 2 132 01/06 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +de 2 133 01/06 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +de 2 134 01/06 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +de 2 135 01/06 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +de 2 136 01/06 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +de 2 137 01/06 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +de 2 138 01/06 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +de 2 139 01/06 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +de 2 140 01/06 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +de 2 141 01/06 20:00 560000.0 560000.0 79.98 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +de 2 142 01/06 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +de 2 143 01/06 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +de 2 144 01/06 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +de 2 145 01/07 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +de 2 146 01/07 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +de 2 147 01/07 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +de 2 148 01/07 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +de 2 149 01/07 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +de 2 150 01/07 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +de 2 151 01/07 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +de 2 152 01/07 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +de 2 153 01/07 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +de 2 154 01/07 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +de 2 155 01/07 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +de 2 156 01/07 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +de 2 157 01/07 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +de 2 158 01/07 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +de 2 159 01/07 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +de 2 160 01/07 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +de 2 161 01/07 16:00 720000.0 720000.0 89.98 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +de 2 162 01/07 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +de 2 163 01/07 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +de 2 164 01/07 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +de 2 165 01/07 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +de 2 166 01/07 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +de 2 167 01/07 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +de 2 168 01/07 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 +de 2 169 01/08 00:00 0.0 0.0 9.98 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +de 2 170 01/08 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +de 2 171 01/08 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +de 2 172 01/08 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +de 2 173 01/08 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +de 2 174 01/08 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +de 2 175 01/08 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +de 2 176 01/08 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +de 2 177 01/08 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +de 2 178 01/08 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +de 2 179 01/08 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +de 2 180 01/08 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +de 2 181 01/08 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +de 2 182 01/08 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +de 2 183 01/08 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +de 2 184 01/08 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +de 2 185 01/08 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +de 2 186 01/08 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +de 2 187 01/08 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +de 2 188 01/08 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +de 2 189 01/08 20:00 20000.0 20000.0 19.98 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +de 2 190 01/08 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +de 2 191 01/08 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +de 2 192 01/08 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +de 2 193 01/09 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +de 2 194 01/09 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +de 2 195 01/09 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +de 2 196 01/09 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +de 2 197 01/09 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +de 2 198 01/09 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +de 2 199 01/09 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +de 2 200 01/09 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +de 2 201 01/09 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +de 2 202 01/09 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +de 2 203 01/09 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +de 2 204 01/09 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +de 2 205 01/09 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +de 2 206 01/09 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +de 2 207 01/09 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +de 2 208 01/09 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +de 2 209 01/09 16:00 60000.0 60000.0 29.98 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +de 2 210 01/09 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +de 2 211 01/09 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +de 2 212 01/09 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +de 2 213 01/09 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +de 2 214 01/09 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +de 2 215 01/09 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +de 2 216 01/09 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +de 2 217 01/10 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +de 2 218 01/10 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +de 2 219 01/10 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +de 2 220 01/10 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +de 2 221 01/10 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +de 2 222 01/10 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +de 2 223 01/10 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +de 2 224 01/10 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +de 2 225 01/10 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +de 2 226 01/10 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +de 2 227 01/10 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +de 2 228 01/10 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +de 2 229 01/10 12:00 120000.0 120000.0 39.98 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +de 2 230 01/10 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +de 2 231 01/10 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +de 2 232 01/10 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +de 2 233 01/10 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +de 2 234 01/10 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +de 2 235 01/10 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +de 2 236 01/10 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +de 2 237 01/10 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +de 2 238 01/10 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +de 2 239 01/10 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +de 2 240 01/10 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +de 2 241 01/11 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +de 2 242 01/11 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +de 2 243 01/11 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +de 2 244 01/11 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +de 2 245 01/11 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +de 2 246 01/11 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +de 2 247 01/11 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +de 2 248 01/11 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +de 2 249 01/11 08:00 200000.0 200000.0 49.98 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +de 2 250 01/11 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +de 2 251 01/11 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +de 2 252 01/11 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +de 2 253 01/11 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +de 2 254 01/11 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +de 2 255 01/11 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +de 2 256 01/11 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +de 2 257 01/11 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +de 2 258 01/11 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +de 2 259 01/11 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +de 2 260 01/11 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +de 2 261 01/11 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +de 2 262 01/11 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +de 2 263 01/11 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +de 2 264 01/11 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +de 2 265 01/12 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +de 2 266 01/12 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +de 2 267 01/12 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +de 2 268 01/12 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +de 2 269 01/12 04:00 300000.0 300000.0 59.98 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +de 2 270 01/12 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +de 2 271 01/12 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +de 2 272 01/12 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +de 2 273 01/12 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +de 2 274 01/12 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +de 2 275 01/12 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +de 2 276 01/12 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +de 2 277 01/12 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +de 2 278 01/12 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +de 2 279 01/12 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +de 2 280 01/12 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +de 2 281 01/12 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +de 2 282 01/12 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +de 2 283 01/12 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +de 2 284 01/12 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +de 2 285 01/12 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +de 2 286 01/12 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +de 2 287 01/12 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +de 2 288 01/12 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +de 2 289 01/13 00:00 420000.0 420000.0 69.98 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +de 2 290 01/13 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +de 2 291 01/13 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +de 2 292 01/13 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +de 2 293 01/13 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +de 2 294 01/13 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +de 2 295 01/13 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +de 2 296 01/13 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +de 2 297 01/13 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +de 2 298 01/13 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +de 2 299 01/13 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +de 2 300 01/13 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +de 2 301 01/13 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +de 2 302 01/13 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +de 2 303 01/13 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +de 2 304 01/13 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +de 2 305 01/13 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +de 2 306 01/13 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +de 2 307 01/13 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +de 2 308 01/13 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +de 2 309 01/13 20:00 560000.0 560000.0 79.98 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +de 2 310 01/13 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +de 2 311 01/13 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +de 2 312 01/13 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +de 2 313 01/14 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +de 2 314 01/14 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +de 2 315 01/14 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +de 2 316 01/14 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +de 2 317 01/14 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +de 2 318 01/14 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +de 2 319 01/14 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +de 2 320 01/14 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +de 2 321 01/14 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +de 2 322 01/14 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +de 2 323 01/14 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +de 2 324 01/14 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +de 2 325 01/14 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +de 2 326 01/14 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +de 2 327 01/14 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +de 2 328 01/14 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +de 2 329 01/14 16:00 720000.0 720000.0 89.98 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +de 2 330 01/14 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +de 2 331 01/14 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +de 2 332 01/14 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +de 2 333 01/14 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +de 2 334 01/14 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +de 2 335 01/14 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +de 2 336 01/14 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 +es 2 1 01/01 00:00 0.0 0.0 9.98 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +es 2 2 01/01 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +es 2 3 01/01 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +es 2 4 01/01 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +es 2 5 01/01 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +es 2 6 01/01 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +es 2 7 01/01 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +es 2 8 01/01 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +es 2 9 01/01 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +es 2 10 01/01 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +es 2 11 01/01 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +es 2 12 01/01 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +es 2 13 01/01 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +es 2 14 01/01 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +es 2 15 01/01 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +es 2 16 01/01 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +es 2 17 01/01 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +es 2 18 01/01 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +es 2 19 01/01 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +es 2 20 01/01 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +es 2 21 01/01 20:00 20000.0 20000.0 19.98 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +es 2 22 01/01 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +es 2 23 01/01 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +es 2 24 01/01 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +es 2 25 01/02 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +es 2 26 01/02 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +es 2 27 01/02 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +es 2 28 01/02 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +es 2 29 01/02 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +es 2 30 01/02 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +es 2 31 01/02 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +es 2 32 01/02 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +es 2 33 01/02 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +es 2 34 01/02 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +es 2 35 01/02 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +es 2 36 01/02 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +es 2 37 01/02 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +es 2 38 01/02 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +es 2 39 01/02 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +es 2 40 01/02 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +es 2 41 01/02 16:00 60000.0 60000.0 29.98 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +es 2 42 01/02 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +es 2 43 01/02 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +es 2 44 01/02 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +es 2 45 01/02 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +es 2 46 01/02 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +es 2 47 01/02 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +es 2 48 01/02 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +es 2 49 01/03 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +es 2 50 01/03 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +es 2 51 01/03 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +es 2 52 01/03 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +es 2 53 01/03 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +es 2 54 01/03 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +es 2 55 01/03 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +es 2 56 01/03 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +es 2 57 01/03 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +es 2 58 01/03 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +es 2 59 01/03 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +es 2 60 01/03 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +es 2 61 01/03 12:00 120000.0 120000.0 39.98 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +es 2 62 01/03 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +es 2 63 01/03 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +es 2 64 01/03 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +es 2 65 01/03 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +es 2 66 01/03 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +es 2 67 01/03 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +es 2 68 01/03 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +es 2 69 01/03 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +es 2 70 01/03 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +es 2 71 01/03 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +es 2 72 01/03 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +es 2 73 01/04 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +es 2 74 01/04 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +es 2 75 01/04 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +es 2 76 01/04 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +es 2 77 01/04 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +es 2 78 01/04 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +es 2 79 01/04 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +es 2 80 01/04 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +es 2 81 01/04 08:00 200000.0 200000.0 49.98 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +es 2 82 01/04 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +es 2 83 01/04 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +es 2 84 01/04 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +es 2 85 01/04 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +es 2 86 01/04 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +es 2 87 01/04 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +es 2 88 01/04 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +es 2 89 01/04 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +es 2 90 01/04 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +es 2 91 01/04 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +es 2 92 01/04 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +es 2 93 01/04 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +es 2 94 01/04 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +es 2 95 01/04 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +es 2 96 01/04 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +es 2 97 01/05 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +es 2 98 01/05 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +es 2 99 01/05 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +es 2 100 01/05 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +es 2 101 01/05 04:00 300000.0 300000.0 59.98 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +es 2 102 01/05 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +es 2 103 01/05 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +es 2 104 01/05 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +es 2 105 01/05 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +es 2 106 01/05 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +es 2 107 01/05 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +es 2 108 01/05 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +es 2 109 01/05 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +es 2 110 01/05 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +es 2 111 01/05 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +es 2 112 01/05 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +es 2 113 01/05 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +es 2 114 01/05 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +es 2 115 01/05 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +es 2 116 01/05 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +es 2 117 01/05 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +es 2 118 01/05 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +es 2 119 01/05 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +es 2 120 01/05 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +es 2 121 01/06 00:00 420000.0 420000.0 69.98 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +es 2 122 01/06 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +es 2 123 01/06 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +es 2 124 01/06 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +es 2 125 01/06 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +es 2 126 01/06 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +es 2 127 01/06 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +es 2 128 01/06 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +es 2 129 01/06 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +es 2 130 01/06 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +es 2 131 01/06 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +es 2 132 01/06 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +es 2 133 01/06 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +es 2 134 01/06 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +es 2 135 01/06 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +es 2 136 01/06 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +es 2 137 01/06 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +es 2 138 01/06 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +es 2 139 01/06 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +es 2 140 01/06 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +es 2 141 01/06 20:00 560000.0 560000.0 79.98 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +es 2 142 01/06 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +es 2 143 01/06 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +es 2 144 01/06 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +es 2 145 01/07 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +es 2 146 01/07 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +es 2 147 01/07 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +es 2 148 01/07 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +es 2 149 01/07 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +es 2 150 01/07 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +es 2 151 01/07 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +es 2 152 01/07 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +es 2 153 01/07 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +es 2 154 01/07 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +es 2 155 01/07 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +es 2 156 01/07 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +es 2 157 01/07 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +es 2 158 01/07 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +es 2 159 01/07 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +es 2 160 01/07 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +es 2 161 01/07 16:00 720000.0 720000.0 89.98 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +es 2 162 01/07 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +es 2 163 01/07 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +es 2 164 01/07 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +es 2 165 01/07 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +es 2 166 01/07 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +es 2 167 01/07 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +es 2 168 01/07 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 +es 2 169 01/08 00:00 0.0 0.0 9.98 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +es 2 170 01/08 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +es 2 171 01/08 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +es 2 172 01/08 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +es 2 173 01/08 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +es 2 174 01/08 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +es 2 175 01/08 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +es 2 176 01/08 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +es 2 177 01/08 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +es 2 178 01/08 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +es 2 179 01/08 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +es 2 180 01/08 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +es 2 181 01/08 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +es 2 182 01/08 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +es 2 183 01/08 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +es 2 184 01/08 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +es 2 185 01/08 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +es 2 186 01/08 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +es 2 187 01/08 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +es 2 188 01/08 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +es 2 189 01/08 20:00 20000.0 20000.0 19.98 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +es 2 190 01/08 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +es 2 191 01/08 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +es 2 192 01/08 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +es 2 193 01/09 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +es 2 194 01/09 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +es 2 195 01/09 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +es 2 196 01/09 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +es 2 197 01/09 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +es 2 198 01/09 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +es 2 199 01/09 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +es 2 200 01/09 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +es 2 201 01/09 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +es 2 202 01/09 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +es 2 203 01/09 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +es 2 204 01/09 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +es 2 205 01/09 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +es 2 206 01/09 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +es 2 207 01/09 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +es 2 208 01/09 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +es 2 209 01/09 16:00 60000.0 60000.0 29.98 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +es 2 210 01/09 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +es 2 211 01/09 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +es 2 212 01/09 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +es 2 213 01/09 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +es 2 214 01/09 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +es 2 215 01/09 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +es 2 216 01/09 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +es 2 217 01/10 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +es 2 218 01/10 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +es 2 219 01/10 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +es 2 220 01/10 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +es 2 221 01/10 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +es 2 222 01/10 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +es 2 223 01/10 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +es 2 224 01/10 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +es 2 225 01/10 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +es 2 226 01/10 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +es 2 227 01/10 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +es 2 228 01/10 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +es 2 229 01/10 12:00 120000.0 120000.0 39.98 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +es 2 230 01/10 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +es 2 231 01/10 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +es 2 232 01/10 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +es 2 233 01/10 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +es 2 234 01/10 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +es 2 235 01/10 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +es 2 236 01/10 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +es 2 237 01/10 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +es 2 238 01/10 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +es 2 239 01/10 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +es 2 240 01/10 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +es 2 241 01/11 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +es 2 242 01/11 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +es 2 243 01/11 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +es 2 244 01/11 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +es 2 245 01/11 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +es 2 246 01/11 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +es 2 247 01/11 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +es 2 248 01/11 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +es 2 249 01/11 08:00 200000.0 200000.0 49.98 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +es 2 250 01/11 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +es 2 251 01/11 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +es 2 252 01/11 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +es 2 253 01/11 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +es 2 254 01/11 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +es 2 255 01/11 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +es 2 256 01/11 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +es 2 257 01/11 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +es 2 258 01/11 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +es 2 259 01/11 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +es 2 260 01/11 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +es 2 261 01/11 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +es 2 262 01/11 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +es 2 263 01/11 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +es 2 264 01/11 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +es 2 265 01/12 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +es 2 266 01/12 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +es 2 267 01/12 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +es 2 268 01/12 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +es 2 269 01/12 04:00 300000.0 300000.0 59.98 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +es 2 270 01/12 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +es 2 271 01/12 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +es 2 272 01/12 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +es 2 273 01/12 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +es 2 274 01/12 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +es 2 275 01/12 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +es 2 276 01/12 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +es 2 277 01/12 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +es 2 278 01/12 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +es 2 279 01/12 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +es 2 280 01/12 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +es 2 281 01/12 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +es 2 282 01/12 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +es 2 283 01/12 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +es 2 284 01/12 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +es 2 285 01/12 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +es 2 286 01/12 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +es 2 287 01/12 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +es 2 288 01/12 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +es 2 289 01/13 00:00 420000.0 420000.0 69.98 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +es 2 290 01/13 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +es 2 291 01/13 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +es 2 292 01/13 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +es 2 293 01/13 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +es 2 294 01/13 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +es 2 295 01/13 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +es 2 296 01/13 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +es 2 297 01/13 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +es 2 298 01/13 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +es 2 299 01/13 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +es 2 300 01/13 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +es 2 301 01/13 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +es 2 302 01/13 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +es 2 303 01/13 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +es 2 304 01/13 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +es 2 305 01/13 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +es 2 306 01/13 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +es 2 307 01/13 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +es 2 308 01/13 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +es 2 309 01/13 20:00 560000.0 560000.0 79.98 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +es 2 310 01/13 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +es 2 311 01/13 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +es 2 312 01/13 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +es 2 313 01/14 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +es 2 314 01/14 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +es 2 315 01/14 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +es 2 316 01/14 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +es 2 317 01/14 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +es 2 318 01/14 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +es 2 319 01/14 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +es 2 320 01/14 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +es 2 321 01/14 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +es 2 322 01/14 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +es 2 323 01/14 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +es 2 324 01/14 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +es 2 325 01/14 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +es 2 326 01/14 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +es 2 327 01/14 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +es 2 328 01/14 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +es 2 329 01/14 16:00 720000.0 720000.0 89.98 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +es 2 330 01/14 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +es 2 331 01/14 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +es 2 332 01/14 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +es 2 333 01/14 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +es 2 334 01/14 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +es 2 335 01/14 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +es 2 336 01/14 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 +fr 2 1 01/01 00:00 0.0 0.0 9.99 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +fr 2 2 01/01 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +fr 2 3 01/01 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +fr 2 4 01/01 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +fr 2 5 01/01 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +fr 2 6 01/01 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +fr 2 7 01/01 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +fr 2 8 01/01 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +fr 2 9 01/01 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +fr 2 10 01/01 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +fr 2 11 01/01 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +fr 2 12 01/01 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +fr 2 13 01/01 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +fr 2 14 01/01 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +fr 2 15 01/01 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +fr 2 16 01/01 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +fr 2 17 01/01 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +fr 2 18 01/01 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +fr 2 19 01/01 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +fr 2 20 01/01 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +fr 2 21 01/01 20:00 20000.0 20000.0 19.99 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +fr 2 22 01/01 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +fr 2 23 01/01 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +fr 2 24 01/01 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +fr 2 25 01/02 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +fr 2 26 01/02 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +fr 2 27 01/02 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +fr 2 28 01/02 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +fr 2 29 01/02 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +fr 2 30 01/02 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +fr 2 31 01/02 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +fr 2 32 01/02 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +fr 2 33 01/02 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +fr 2 34 01/02 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +fr 2 35 01/02 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +fr 2 36 01/02 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +fr 2 37 01/02 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +fr 2 38 01/02 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +fr 2 39 01/02 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +fr 2 40 01/02 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +fr 2 41 01/02 16:00 60000.0 60000.0 29.99 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +fr 2 42 01/02 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +fr 2 43 01/02 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +fr 2 44 01/02 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +fr 2 45 01/02 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +fr 2 46 01/02 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +fr 2 47 01/02 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +fr 2 48 01/02 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +fr 2 49 01/03 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +fr 2 50 01/03 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +fr 2 51 01/03 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +fr 2 52 01/03 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +fr 2 53 01/03 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +fr 2 54 01/03 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +fr 2 55 01/03 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +fr 2 56 01/03 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +fr 2 57 01/03 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +fr 2 58 01/03 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +fr 2 59 01/03 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +fr 2 60 01/03 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +fr 2 61 01/03 12:00 120000.0 120000.0 39.99 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +fr 2 62 01/03 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +fr 2 63 01/03 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +fr 2 64 01/03 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +fr 2 65 01/03 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +fr 2 66 01/03 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +fr 2 67 01/03 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +fr 2 68 01/03 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +fr 2 69 01/03 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +fr 2 70 01/03 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +fr 2 71 01/03 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +fr 2 72 01/03 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +fr 2 73 01/04 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +fr 2 74 01/04 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +fr 2 75 01/04 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +fr 2 76 01/04 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +fr 2 77 01/04 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +fr 2 78 01/04 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +fr 2 79 01/04 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +fr 2 80 01/04 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +fr 2 81 01/04 08:00 200000.0 200000.0 49.99 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +fr 2 82 01/04 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +fr 2 83 01/04 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +fr 2 84 01/04 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +fr 2 85 01/04 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +fr 2 86 01/04 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +fr 2 87 01/04 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +fr 2 88 01/04 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +fr 2 89 01/04 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +fr 2 90 01/04 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +fr 2 91 01/04 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +fr 2 92 01/04 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +fr 2 93 01/04 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +fr 2 94 01/04 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +fr 2 95 01/04 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +fr 2 96 01/04 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +fr 2 97 01/05 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +fr 2 98 01/05 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +fr 2 99 01/05 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +fr 2 100 01/05 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +fr 2 101 01/05 04:00 300000.0 300000.0 59.99 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +fr 2 102 01/05 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +fr 2 103 01/05 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +fr 2 104 01/05 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +fr 2 105 01/05 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +fr 2 106 01/05 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +fr 2 107 01/05 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +fr 2 108 01/05 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +fr 2 109 01/05 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +fr 2 110 01/05 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +fr 2 111 01/05 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +fr 2 112 01/05 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +fr 2 113 01/05 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +fr 2 114 01/05 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +fr 2 115 01/05 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +fr 2 116 01/05 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +fr 2 117 01/05 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +fr 2 118 01/05 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +fr 2 119 01/05 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +fr 2 120 01/05 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +fr 2 121 01/06 00:00 420000.0 420000.0 69.99 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +fr 2 122 01/06 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +fr 2 123 01/06 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +fr 2 124 01/06 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +fr 2 125 01/06 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +fr 2 126 01/06 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +fr 2 127 01/06 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +fr 2 128 01/06 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +fr 2 129 01/06 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +fr 2 130 01/06 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +fr 2 131 01/06 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +fr 2 132 01/06 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +fr 2 133 01/06 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +fr 2 134 01/06 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +fr 2 135 01/06 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +fr 2 136 01/06 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +fr 2 137 01/06 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +fr 2 138 01/06 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +fr 2 139 01/06 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +fr 2 140 01/06 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +fr 2 141 01/06 20:00 560000.0 560000.0 79.99 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +fr 2 142 01/06 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +fr 2 143 01/06 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +fr 2 144 01/06 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +fr 2 145 01/07 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +fr 2 146 01/07 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +fr 2 147 01/07 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +fr 2 148 01/07 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +fr 2 149 01/07 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +fr 2 150 01/07 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +fr 2 151 01/07 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +fr 2 152 01/07 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +fr 2 153 01/07 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +fr 2 154 01/07 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +fr 2 155 01/07 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +fr 2 156 01/07 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +fr 2 157 01/07 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +fr 2 158 01/07 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +fr 2 159 01/07 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +fr 2 160 01/07 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +fr 2 161 01/07 16:00 720000.0 720000.0 89.99 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +fr 2 162 01/07 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +fr 2 163 01/07 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +fr 2 164 01/07 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +fr 2 165 01/07 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +fr 2 166 01/07 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +fr 2 167 01/07 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +fr 2 168 01/07 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 +fr 2 169 01/08 00:00 0.0 0.0 9.99 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 18000.0 18000.0 0.0 0.0 +fr 2 170 01/08 01:00 1000.0 1000.0 10.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17900.0 17900.0 0.0 1.0 +fr 2 171 01/08 02:00 2000.0 2000.0 10.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17800.0 17800.0 0.0 1.0 +fr 2 172 01/08 03:00 3000.0 3000.0 10.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17700.0 17700.0 0.0 1.0 +fr 2 173 01/08 04:00 4000.0 4000.0 10.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17600.0 17600.0 0.0 1.0 +fr 2 174 01/08 05:00 5000.0 5000.0 10.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17500.0 17500.0 0.0 1.0 +fr 2 175 01/08 06:00 6000.0 6000.0 10.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17400.0 17400.0 0.0 1.0 +fr 2 176 01/08 07:00 7000.0 7000.0 10.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17300.0 17300.0 0.0 1.0 +fr 2 177 01/08 08:00 8000.0 8000.0 10.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17200.0 17200.0 0.0 1.0 +fr 2 178 01/08 09:00 9000.0 9000.0 10.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17100.0 17100.0 0.0 1.0 +fr 2 179 01/08 10:00 10000.0 10000.0 10.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 17000.0 17000.0 0.0 1.0 +fr 2 180 01/08 11:00 11000.0 11000.0 10.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16900.0 16900.0 0.0 1.0 +fr 2 181 01/08 12:00 12000.0 12000.0 10.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16800.0 16800.0 0.0 1.0 +fr 2 182 01/08 13:00 13000.0 13000.0 10.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16700.0 16700.0 0.0 1.0 +fr 2 183 01/08 14:00 14000.0 14000.0 10.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16600.0 16600.0 0.0 1.0 +fr 2 184 01/08 15:00 15000.0 15000.0 10.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16500.0 16500.0 0.0 1.0 +fr 2 185 01/08 16:00 16000.0 16000.0 10.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16400.0 16400.0 0.0 1.0 +fr 2 186 01/08 17:00 17000.0 17000.0 10.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16300.0 16300.0 0.0 1.0 +fr 2 187 01/08 18:00 18000.0 18000.0 10.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16200.0 16200.0 0.0 1.0 +fr 2 188 01/08 19:00 19000.0 19000.0 10.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16100.0 16100.0 0.0 1.0 +fr 2 189 01/08 20:00 20000.0 20000.0 19.99 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 16000.0 16000.0 0.0 1.0 +fr 2 190 01/08 21:00 22000.0 22000.0 20.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15900.0 15900.0 0.0 2.0 +fr 2 191 01/08 22:00 24000.0 24000.0 20.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15800.0 15800.0 0.0 2.0 +fr 2 192 01/08 23:00 26000.0 26000.0 20.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15700.0 15700.0 0.0 2.0 +fr 2 193 01/09 00:00 28000.0 28000.0 20.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15600.0 15600.0 0.0 2.0 +fr 2 194 01/09 01:00 30000.0 30000.0 20.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15500.0 15500.0 0.0 2.0 +fr 2 195 01/09 02:00 32000.0 32000.0 20.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15400.0 15400.0 0.0 2.0 +fr 2 196 01/09 03:00 34000.0 34000.0 20.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15300.0 15300.0 0.0 2.0 +fr 2 197 01/09 04:00 36000.0 36000.0 20.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15200.0 15200.0 0.0 2.0 +fr 2 198 01/09 05:00 38000.0 38000.0 20.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15100.0 15100.0 0.0 2.0 +fr 2 199 01/09 06:00 40000.0 40000.0 20.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 15000.0 15000.0 0.0 2.0 +fr 2 200 01/09 07:00 42000.0 42000.0 20.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14900.0 14900.0 0.0 2.0 +fr 2 201 01/09 08:00 44000.0 44000.0 20.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14800.0 14800.0 0.0 2.0 +fr 2 202 01/09 09:00 46000.0 46000.0 20.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14700.0 14700.0 0.0 2.0 +fr 2 203 01/09 10:00 48000.0 48000.0 20.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14600.0 14600.0 0.0 2.0 +fr 2 204 01/09 11:00 50000.0 50000.0 20.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14500.0 14500.0 0.0 2.0 +fr 2 205 01/09 12:00 52000.0 52000.0 20.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14400.0 14400.0 0.0 2.0 +fr 2 206 01/09 13:00 54000.0 54000.0 20.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14300.0 14300.0 0.0 2.0 +fr 2 207 01/09 14:00 56000.0 56000.0 20.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14200.0 14200.0 0.0 2.0 +fr 2 208 01/09 15:00 58000.0 58000.0 20.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14100.0 14100.0 0.0 2.0 +fr 2 209 01/09 16:00 60000.0 60000.0 29.99 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 14000.0 14000.0 0.0 2.0 +fr 2 210 01/09 17:00 63000.0 63000.0 30.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13900.0 13900.0 0.0 3.0 +fr 2 211 01/09 18:00 66000.0 66000.0 30.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13800.0 13800.0 0.0 3.0 +fr 2 212 01/09 19:00 69000.0 69000.0 30.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13700.0 13700.0 0.0 3.0 +fr 2 213 01/09 20:00 72000.0 72000.0 30.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13600.0 13600.0 0.0 3.0 +fr 2 214 01/09 21:00 75000.0 75000.0 30.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13500.0 13500.0 0.0 3.0 +fr 2 215 01/09 22:00 78000.0 78000.0 30.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13400.0 13400.0 0.0 3.0 +fr 2 216 01/09 23:00 81000.0 81000.0 30.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13300.0 13300.0 0.0 3.0 +fr 2 217 01/10 00:00 84000.0 84000.0 30.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13200.0 13200.0 0.0 3.0 +fr 2 218 01/10 01:00 87000.0 87000.0 30.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13100.0 13100.0 0.0 3.0 +fr 2 219 01/10 02:00 90000.0 90000.0 30.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 13000.0 13000.0 0.0 3.0 +fr 2 220 01/10 03:00 93000.0 93000.0 30.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12900.0 12900.0 0.0 3.0 +fr 2 221 01/10 04:00 96000.0 96000.0 30.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12800.0 12800.0 0.0 3.0 +fr 2 222 01/10 05:00 99000.0 99000.0 30.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12700.0 12700.0 0.0 3.0 +fr 2 223 01/10 06:00 102000.0 102000.0 30.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12600.0 12600.0 0.0 3.0 +fr 2 224 01/10 07:00 105000.0 105000.0 30.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12500.0 12500.0 0.0 3.0 +fr 2 225 01/10 08:00 108000.0 108000.0 30.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12400.0 12400.0 0.0 3.0 +fr 2 226 01/10 09:00 111000.0 111000.0 30.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12300.0 12300.0 0.0 3.0 +fr 2 227 01/10 10:00 114000.0 114000.0 30.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12200.0 12200.0 0.0 3.0 +fr 2 228 01/10 11:00 117000.0 117000.0 30.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12100.0 12100.0 0.0 3.0 +fr 2 229 01/10 12:00 120000.0 120000.0 39.99 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 12000.0 12000.0 0.0 3.0 +fr 2 230 01/10 13:00 124000.0 124000.0 40.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11900.0 11900.0 0.0 4.0 +fr 2 231 01/10 14:00 128000.0 128000.0 40.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11800.0 11800.0 0.0 4.0 +fr 2 232 01/10 15:00 132000.0 132000.0 40.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11700.0 11700.0 0.0 4.0 +fr 2 233 01/10 16:00 136000.0 136000.0 40.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11600.0 11600.0 0.0 4.0 +fr 2 234 01/10 17:00 140000.0 140000.0 40.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11500.0 11500.0 0.0 4.0 +fr 2 235 01/10 18:00 144000.0 144000.0 40.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11400.0 11400.0 0.0 4.0 +fr 2 236 01/10 19:00 148000.0 148000.0 40.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11300.0 11300.0 0.0 4.0 +fr 2 237 01/10 20:00 152000.0 152000.0 40.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11200.0 11200.0 0.0 4.0 +fr 2 238 01/10 21:00 156000.0 156000.0 40.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11100.0 11100.0 0.0 4.0 +fr 2 239 01/10 22:00 160000.0 160000.0 40.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 11000.0 11000.0 0.0 4.0 +fr 2 240 01/10 23:00 164000.0 164000.0 40.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10900.0 10900.0 0.0 4.0 +fr 2 241 01/11 00:00 168000.0 168000.0 40.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10800.0 10800.0 0.0 4.0 +fr 2 242 01/11 01:00 172000.0 172000.0 40.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10700.0 10700.0 0.0 4.0 +fr 2 243 01/11 02:00 176000.0 176000.0 40.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10600.0 10600.0 0.0 4.0 +fr 2 244 01/11 03:00 180000.0 180000.0 40.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10500.0 10500.0 0.0 4.0 +fr 2 245 01/11 04:00 184000.0 184000.0 40.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10400.0 10400.0 0.0 4.0 +fr 2 246 01/11 05:00 188000.0 188000.0 40.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10300.0 10300.0 0.0 4.0 +fr 2 247 01/11 06:00 192000.0 192000.0 40.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10200.0 10200.0 0.0 4.0 +fr 2 248 01/11 07:00 196000.0 196000.0 40.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10100.0 10100.0 0.0 4.0 +fr 2 249 01/11 08:00 200000.0 200000.0 49.99 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 10000.0 10000.0 0.0 4.0 +fr 2 250 01/11 09:00 205000.0 205000.0 50.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9900.0 9900.0 0.0 5.0 +fr 2 251 01/11 10:00 210000.0 210000.0 50.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9800.0 9800.0 0.0 5.0 +fr 2 252 01/11 11:00 215000.0 215000.0 50.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9700.0 9700.0 0.0 5.0 +fr 2 253 01/11 12:00 220000.0 220000.0 50.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9600.0 9600.0 0.0 5.0 +fr 2 254 01/11 13:00 225000.0 225000.0 50.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9500.0 9500.0 0.0 5.0 +fr 2 255 01/11 14:00 230000.0 230000.0 50.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9400.0 9400.0 0.0 5.0 +fr 2 256 01/11 15:00 235000.0 235000.0 50.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9300.0 9300.0 0.0 5.0 +fr 2 257 01/11 16:00 240000.0 240000.0 50.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9200.0 9200.0 0.0 5.0 +fr 2 258 01/11 17:00 245000.0 245000.0 50.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9100.0 9100.0 0.0 5.0 +fr 2 259 01/11 18:00 250000.0 250000.0 50.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 9000.0 9000.0 0.0 5.0 +fr 2 260 01/11 19:00 255000.0 255000.0 50.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8900.0 8900.0 0.0 5.0 +fr 2 261 01/11 20:00 260000.0 260000.0 50.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8800.0 8800.0 0.0 5.0 +fr 2 262 01/11 21:00 265000.0 265000.0 50.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8700.0 8700.0 0.0 5.0 +fr 2 263 01/11 22:00 270000.0 270000.0 50.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8600.0 8600.0 0.0 5.0 +fr 2 264 01/11 23:00 275000.0 275000.0 50.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8500.0 8500.0 0.0 5.0 +fr 2 265 01/12 00:00 280000.0 280000.0 50.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8400.0 8400.0 0.0 5.0 +fr 2 266 01/12 01:00 285000.0 285000.0 50.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8300.0 8300.0 0.0 5.0 +fr 2 267 01/12 02:00 290000.0 290000.0 50.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8200.0 8200.0 0.0 5.0 +fr 2 268 01/12 03:00 295000.0 295000.0 50.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8100.0 8100.0 0.0 5.0 +fr 2 269 01/12 04:00 300000.0 300000.0 59.99 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 8000.0 8000.0 0.0 5.0 +fr 2 270 01/12 05:00 306000.0 306000.0 60.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7900.0 7900.0 0.0 6.0 +fr 2 271 01/12 06:00 312000.0 312000.0 60.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7800.0 7800.0 0.0 6.0 +fr 2 272 01/12 07:00 318000.0 318000.0 60.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7700.0 7700.0 0.0 6.0 +fr 2 273 01/12 08:00 324000.0 324000.0 60.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7600.0 7600.0 0.0 6.0 +fr 2 274 01/12 09:00 330000.0 330000.0 60.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7500.0 7500.0 0.0 6.0 +fr 2 275 01/12 10:00 336000.0 336000.0 60.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7400.0 7400.0 0.0 6.0 +fr 2 276 01/12 11:00 342000.0 342000.0 60.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7300.0 7300.0 0.0 6.0 +fr 2 277 01/12 12:00 348000.0 348000.0 60.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7200.0 7200.0 0.0 6.0 +fr 2 278 01/12 13:00 354000.0 354000.0 60.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 10900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7100.0 7100.0 0.0 6.0 +fr 2 279 01/12 14:00 360000.0 360000.0 60.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 7000.0 7000.0 0.0 6.0 +fr 2 280 01/12 15:00 366000.0 366000.0 60.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6900.0 6900.0 0.0 6.0 +fr 2 281 01/12 16:00 372000.0 372000.0 60.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6800.0 6800.0 0.0 6.0 +fr 2 282 01/12 17:00 378000.0 378000.0 60.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6700.0 6700.0 0.0 6.0 +fr 2 283 01/12 18:00 384000.0 384000.0 60.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6600.0 6600.0 0.0 6.0 +fr 2 284 01/12 19:00 390000.0 390000.0 60.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6500.0 6500.0 0.0 6.0 +fr 2 285 01/12 20:00 396000.0 396000.0 60.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6400.0 6400.0 0.0 6.0 +fr 2 286 01/12 21:00 402000.0 402000.0 60.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6300.0 6300.0 0.0 6.0 +fr 2 287 01/12 22:00 408000.0 408000.0 60.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6200.0 6200.0 0.0 6.0 +fr 2 288 01/12 23:00 414000.0 414000.0 60.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6100.0 6100.0 0.0 6.0 +fr 2 289 01/13 00:00 420000.0 420000.0 69.99 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 6000.0 6000.0 0.0 6.0 +fr 2 290 01/13 01:00 427000.0 427000.0 70.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5900.0 5900.0 0.0 7.0 +fr 2 291 01/13 02:00 434000.0 434000.0 70.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5800.0 5800.0 0.0 7.0 +fr 2 292 01/13 03:00 441000.0 441000.0 70.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5700.0 5700.0 0.0 7.0 +fr 2 293 01/13 04:00 448000.0 448000.0 70.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5600.0 5600.0 0.0 7.0 +fr 2 294 01/13 05:00 455000.0 455000.0 70.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5500.0 5500.0 0.0 7.0 +fr 2 295 01/13 06:00 462000.0 462000.0 70.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5400.0 5400.0 0.0 7.0 +fr 2 296 01/13 07:00 469000.0 469000.0 70.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5300.0 5300.0 0.0 7.0 +fr 2 297 01/13 08:00 476000.0 476000.0 70.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5200.0 5200.0 0.0 7.0 +fr 2 298 01/13 09:00 483000.0 483000.0 70.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 12900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5100.0 5100.0 0.0 7.0 +fr 2 299 01/13 10:00 490000.0 490000.0 70.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 5000.0 5000.0 0.0 7.0 +fr 2 300 01/13 11:00 497000.0 497000.0 70.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4900.0 4900.0 0.0 7.0 +fr 2 301 01/13 12:00 504000.0 504000.0 70.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4800.0 4800.0 0.0 7.0 +fr 2 302 01/13 13:00 511000.0 511000.0 70.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4700.0 4700.0 0.0 7.0 +fr 2 303 01/13 14:00 518000.0 518000.0 70.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4600.0 4600.0 0.0 7.0 +fr 2 304 01/13 15:00 525000.0 525000.0 70.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4500.0 4500.0 0.0 7.0 +fr 2 305 01/13 16:00 532000.0 532000.0 70.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4400.0 4400.0 0.0 7.0 +fr 2 306 01/13 17:00 539000.0 539000.0 70.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4300.0 4300.0 0.0 7.0 +fr 2 307 01/13 18:00 546000.0 546000.0 70.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4200.0 4200.0 0.0 7.0 +fr 2 308 01/13 19:00 553000.0 553000.0 70.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 13900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4100.0 4100.0 0.0 7.0 +fr 2 309 01/13 20:00 560000.0 560000.0 79.99 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 4000.0 4000.0 0.0 7.0 +fr 2 310 01/13 21:00 568000.0 568000.0 80.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3900.0 3900.0 0.0 8.0 +fr 2 311 01/13 22:00 576000.0 576000.0 80.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3800.0 3800.0 0.0 8.0 +fr 2 312 01/13 23:00 584000.0 584000.0 80.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3700.0 3700.0 0.0 8.0 +fr 2 313 01/14 00:00 592000.0 592000.0 80.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3600.0 3600.0 0.0 8.0 +fr 2 314 01/14 01:00 600000.0 600000.0 80.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3500.0 3500.0 0.0 8.0 +fr 2 315 01/14 02:00 608000.0 608000.0 80.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3400.0 3400.0 0.0 8.0 +fr 2 316 01/14 03:00 616000.0 616000.0 80.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3300.0 3300.0 0.0 8.0 +fr 2 317 01/14 04:00 624000.0 624000.0 80.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3200.0 3200.0 0.0 8.0 +fr 2 318 01/14 05:00 632000.0 632000.0 80.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 14900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3100.0 3100.0 0.0 8.0 +fr 2 319 01/14 06:00 640000.0 640000.0 80.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 3000.0 3000.0 0.0 8.0 +fr 2 320 01/14 07:00 648000.0 648000.0 80.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2900.0 2900.0 0.0 8.0 +fr 2 321 01/14 08:00 656000.0 656000.0 80.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2800.0 2800.0 0.0 8.0 +fr 2 322 01/14 09:00 664000.0 664000.0 80.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2700.0 2700.0 0.0 8.0 +fr 2 323 01/14 10:00 672000.0 672000.0 80.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2600.0 2600.0 0.0 8.0 +fr 2 324 01/14 11:00 680000.0 680000.0 80.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2500.0 2500.0 0.0 8.0 +fr 2 325 01/14 12:00 688000.0 688000.0 80.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2400.0 2400.0 0.0 8.0 +fr 2 326 01/14 13:00 696000.0 696000.0 80.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2300.0 2300.0 0.0 8.0 +fr 2 327 01/14 14:00 704000.0 704000.0 80.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15800.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2200.0 2200.0 0.0 8.0 +fr 2 328 01/14 15:00 712000.0 712000.0 80.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 15900.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2100.0 2100.0 0.0 8.0 +fr 2 329 01/14 16:00 720000.0 720000.0 89.99 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16000.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 2000.0 2000.0 0.0 8.0 +fr 2 330 01/14 17:00 729000.0 729000.0 90.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16100.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1900.0 1900.0 0.0 9.0 +fr 2 331 01/14 18:00 738000.0 738000.0 90.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16200.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1800.0 1800.0 0.0 9.0 +fr 2 332 01/14 19:00 747000.0 747000.0 90.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16300.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1700.0 1700.0 0.0 9.0 +fr 2 333 01/14 20:00 756000.0 756000.0 90.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16400.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1600.0 1600.0 0.0 9.0 +fr 2 334 01/14 21:00 765000.0 765000.0 90.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16500.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1500.0 1500.0 0.0 9.0 +fr 2 335 01/14 22:00 774000.0 774000.0 90.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1400.0 1400.0 0.0 9.0 +fr 2 336 01/14 23:00 783000.0 783000.0 90.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 16700.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 18000.0 1300.0 1300.0 0.0 9.0 diff --git a/tests/integration/raw_studies_blueprint/assets/aggregate_areas_raw_data/test-05.result.tsv b/tests/integration/raw_studies_blueprint/assets/aggregate_areas_raw_data/test-05.result.tsv new file mode 100644 index 0000000000..61ff1bf485 --- /dev/null +++ b/tests/integration/raw_studies_blueprint/assets/aggregate_areas_raw_data/test-05.result.tsv @@ -0,0 +1,5 @@ +area mcYear timeId time OV. COST OP. COST MRG. PRICE CO2 EMIS. BALANCE ROW BAL. PSP MISC. NDG LOAD H. ROR WIND SOLAR NUCLEAR LIGNITE COAL GAS OIL MIX. FUEL MISC. DTG H. STOR H. PUMP H. LEV H. INFL H. OVFL H. VAL H. COST UNSP. ENRG SPIL. ENRG LOLD LOLP AVL DTG DTG MRG MAX MRG NP COST NODU +de 1 1 2030 92904000.0 92904000.0 47.14 0.0 0.0 0.0 0.0 0.0 2805600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2805600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6048000.0 3242400.0 3242400.0 0.0 1566.0 +es 1 1 2030 92904000.0 92904000.0 47.14 0.0 0.0 0.0 0.0 0.0 2805600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2805600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6048000.0 3242400.0 3242400.0 0.0 1566.0 +de 2 1 2030 92904000.0 92904000.0 47.14 0.0 0.0 0.0 0.0 0.0 2805600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2805600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6048000.0 3242400.0 3242400.0 0.0 1566.0 +es 2 1 2030 92904000.0 92904000.0 47.14 0.0 0.0 0.0 0.0 0.0 2805600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2805600.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6048000.0 3242400.0 3242400.0 0.0 1566.0 diff --git a/tests/integration/raw_studies_blueprint/assets/aggregate_links_raw_data/test-01.result.tsv b/tests/integration/raw_studies_blueprint/assets/aggregate_links_raw_data/test-01.result.tsv new file mode 100644 index 0000000000..fc82eb62c5 --- /dev/null +++ b/tests/integration/raw_studies_blueprint/assets/aggregate_links_raw_data/test-01.result.tsv @@ -0,0 +1,2017 @@ +link mcYear timeId time FLOW LIN. UCAP LIN. LOOP FLOW FLOW QUAD. CONG. FEE (ALG.) CONG. FEE (ABS.) MARG. COST CONG. PROB + CONG. PROB - HURDLE COST +de - fr 1 1 01/01 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 2 01/01 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 3 01/01 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 4 01/01 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 5 01/01 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 6 01/01 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 7 01/01 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 8 01/01 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 9 01/01 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 10 01/01 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 11 01/01 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 12 01/01 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 13 01/01 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 14 01/01 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 15 01/01 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 16 01/01 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 17 01/01 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 18 01/01 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 19 01/01 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 20 01/01 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 21 01/01 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 22 01/01 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 23 01/01 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 24 01/01 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 25 01/02 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 26 01/02 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 27 01/02 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 28 01/02 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 29 01/02 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 30 01/02 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 31 01/02 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 32 01/02 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 33 01/02 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 34 01/02 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 35 01/02 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 36 01/02 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 37 01/02 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 38 01/02 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 39 01/02 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 40 01/02 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 41 01/02 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 42 01/02 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 43 01/02 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 44 01/02 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 45 01/02 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 46 01/02 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 47 01/02 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 48 01/02 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 49 01/03 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 50 01/03 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 51 01/03 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 52 01/03 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 53 01/03 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 54 01/03 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 55 01/03 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 56 01/03 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 57 01/03 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 58 01/03 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 59 01/03 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 60 01/03 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 61 01/03 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 62 01/03 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 63 01/03 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 64 01/03 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 65 01/03 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 66 01/03 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 67 01/03 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 68 01/03 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 69 01/03 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 70 01/03 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 71 01/03 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 72 01/03 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 73 01/04 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 74 01/04 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 75 01/04 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 76 01/04 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 77 01/04 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 78 01/04 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 79 01/04 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 80 01/04 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 81 01/04 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 82 01/04 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 83 01/04 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 84 01/04 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 85 01/04 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 86 01/04 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 87 01/04 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 88 01/04 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 89 01/04 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 90 01/04 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 91 01/04 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 92 01/04 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 93 01/04 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 94 01/04 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 95 01/04 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 96 01/04 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 97 01/05 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 98 01/05 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 99 01/05 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 100 01/05 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 101 01/05 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 102 01/05 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 103 01/05 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 104 01/05 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 105 01/05 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 106 01/05 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 107 01/05 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 108 01/05 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 109 01/05 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 110 01/05 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 111 01/05 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 112 01/05 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 113 01/05 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 114 01/05 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 115 01/05 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 116 01/05 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 117 01/05 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 118 01/05 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 119 01/05 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 120 01/05 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 121 01/06 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 122 01/06 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 123 01/06 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 124 01/06 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 125 01/06 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 126 01/06 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 127 01/06 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 128 01/06 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 129 01/06 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 130 01/06 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 131 01/06 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 132 01/06 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 133 01/06 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 134 01/06 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 135 01/06 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 136 01/06 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 137 01/06 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 138 01/06 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 139 01/06 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 140 01/06 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 141 01/06 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 142 01/06 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 143 01/06 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 144 01/06 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 145 01/07 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 146 01/07 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 147 01/07 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 148 01/07 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 149 01/07 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 150 01/07 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 151 01/07 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 152 01/07 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 153 01/07 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 154 01/07 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 155 01/07 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 156 01/07 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 157 01/07 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 158 01/07 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 159 01/07 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 160 01/07 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 161 01/07 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 162 01/07 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 163 01/07 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 164 01/07 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 165 01/07 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 166 01/07 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 167 01/07 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 168 01/07 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 169 01/08 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 170 01/08 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 171 01/08 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 172 01/08 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 173 01/08 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 174 01/08 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 175 01/08 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 176 01/08 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 177 01/08 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 178 01/08 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 179 01/08 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 180 01/08 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 181 01/08 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 182 01/08 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 183 01/08 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 184 01/08 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 185 01/08 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 186 01/08 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 187 01/08 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 188 01/08 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 189 01/08 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 190 01/08 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 191 01/08 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 192 01/08 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 193 01/09 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 194 01/09 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 195 01/09 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 196 01/09 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 197 01/09 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 198 01/09 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 199 01/09 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 200 01/09 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 201 01/09 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 202 01/09 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 203 01/09 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 204 01/09 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 205 01/09 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 206 01/09 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 207 01/09 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 208 01/09 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 209 01/09 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 210 01/09 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 211 01/09 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 212 01/09 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 213 01/09 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 214 01/09 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 215 01/09 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 216 01/09 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 217 01/10 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 218 01/10 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 219 01/10 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 220 01/10 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 221 01/10 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 222 01/10 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 223 01/10 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 224 01/10 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 225 01/10 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 226 01/10 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 227 01/10 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 228 01/10 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 229 01/10 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 230 01/10 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 231 01/10 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 232 01/10 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 233 01/10 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 234 01/10 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 235 01/10 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 236 01/10 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 237 01/10 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 238 01/10 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 239 01/10 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 240 01/10 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 241 01/11 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 242 01/11 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 243 01/11 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 244 01/11 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 245 01/11 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 246 01/11 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 247 01/11 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 248 01/11 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 249 01/11 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 250 01/11 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 251 01/11 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 252 01/11 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 253 01/11 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 254 01/11 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 255 01/11 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 256 01/11 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 257 01/11 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 258 01/11 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 259 01/11 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 260 01/11 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 261 01/11 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 262 01/11 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 263 01/11 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 264 01/11 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 265 01/12 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 266 01/12 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 267 01/12 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 268 01/12 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 269 01/12 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 270 01/12 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 271 01/12 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 272 01/12 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 273 01/12 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 274 01/12 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 275 01/12 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 276 01/12 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 277 01/12 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 278 01/12 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 279 01/12 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 280 01/12 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 281 01/12 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 282 01/12 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 283 01/12 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 284 01/12 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 285 01/12 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 286 01/12 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 287 01/12 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 288 01/12 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 289 01/13 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 290 01/13 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 291 01/13 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 292 01/13 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 293 01/13 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 294 01/13 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 295 01/13 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 296 01/13 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 297 01/13 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 298 01/13 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 299 01/13 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 300 01/13 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 301 01/13 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 302 01/13 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 303 01/13 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 304 01/13 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 305 01/13 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 306 01/13 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 307 01/13 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 308 01/13 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 309 01/13 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 310 01/13 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 311 01/13 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 312 01/13 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 313 01/14 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 314 01/14 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 315 01/14 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 316 01/14 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 317 01/14 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 318 01/14 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 319 01/14 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 320 01/14 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 321 01/14 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 322 01/14 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 323 01/14 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 324 01/14 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 325 01/14 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 326 01/14 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 327 01/14 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 328 01/14 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 329 01/14 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 330 01/14 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 331 01/14 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 332 01/14 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 333 01/14 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 334 01/14 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 335 01/14 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 336 01/14 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 1 01/01 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 2 01/01 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 3 01/01 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 4 01/01 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 5 01/01 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 6 01/01 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 7 01/01 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 8 01/01 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 9 01/01 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 10 01/01 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 11 01/01 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 12 01/01 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 13 01/01 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 14 01/01 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 15 01/01 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 16 01/01 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 17 01/01 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 18 01/01 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 19 01/01 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 20 01/01 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 21 01/01 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 22 01/01 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 23 01/01 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 24 01/01 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 25 01/02 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 26 01/02 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 27 01/02 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 28 01/02 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 29 01/02 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 30 01/02 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 31 01/02 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 32 01/02 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 33 01/02 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 34 01/02 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 35 01/02 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 36 01/02 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 37 01/02 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 38 01/02 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 39 01/02 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 40 01/02 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 41 01/02 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 42 01/02 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 43 01/02 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 44 01/02 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 45 01/02 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 46 01/02 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 47 01/02 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 48 01/02 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 49 01/03 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 50 01/03 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 51 01/03 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 52 01/03 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 53 01/03 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 54 01/03 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 55 01/03 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 56 01/03 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 57 01/03 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 58 01/03 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 59 01/03 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 60 01/03 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 61 01/03 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 62 01/03 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 63 01/03 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 64 01/03 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 65 01/03 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 66 01/03 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 67 01/03 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 68 01/03 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 69 01/03 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 70 01/03 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 71 01/03 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 72 01/03 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 73 01/04 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 74 01/04 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 75 01/04 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 76 01/04 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 77 01/04 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 78 01/04 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 79 01/04 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 80 01/04 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 81 01/04 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 82 01/04 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 83 01/04 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 84 01/04 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 85 01/04 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 86 01/04 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 87 01/04 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 88 01/04 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 89 01/04 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 90 01/04 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 91 01/04 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 92 01/04 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 93 01/04 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 94 01/04 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 95 01/04 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 96 01/04 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 97 01/05 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 98 01/05 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 99 01/05 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 100 01/05 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 101 01/05 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 102 01/05 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 103 01/05 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 104 01/05 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 105 01/05 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 106 01/05 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 107 01/05 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 108 01/05 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 109 01/05 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 110 01/05 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 111 01/05 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 112 01/05 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 113 01/05 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 114 01/05 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 115 01/05 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 116 01/05 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 117 01/05 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 118 01/05 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 119 01/05 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 120 01/05 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 121 01/06 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 122 01/06 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 123 01/06 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 124 01/06 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 125 01/06 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 126 01/06 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 127 01/06 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 128 01/06 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 129 01/06 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 130 01/06 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 131 01/06 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 132 01/06 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 133 01/06 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 134 01/06 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 135 01/06 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 136 01/06 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 137 01/06 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 138 01/06 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 139 01/06 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 140 01/06 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 141 01/06 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 142 01/06 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 143 01/06 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 144 01/06 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 145 01/07 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 146 01/07 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 147 01/07 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 148 01/07 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 149 01/07 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 150 01/07 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 151 01/07 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 152 01/07 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 153 01/07 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 154 01/07 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 155 01/07 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 156 01/07 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 157 01/07 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 158 01/07 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 159 01/07 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 160 01/07 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 161 01/07 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 162 01/07 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 163 01/07 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 164 01/07 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 165 01/07 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 166 01/07 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 167 01/07 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 168 01/07 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 169 01/08 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 170 01/08 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 171 01/08 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 172 01/08 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 173 01/08 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 174 01/08 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 175 01/08 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 176 01/08 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 177 01/08 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 178 01/08 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 179 01/08 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 180 01/08 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 181 01/08 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 182 01/08 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 183 01/08 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 184 01/08 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 185 01/08 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 186 01/08 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 187 01/08 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 188 01/08 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 189 01/08 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 190 01/08 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 191 01/08 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 192 01/08 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 193 01/09 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 194 01/09 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 195 01/09 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 196 01/09 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 197 01/09 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 198 01/09 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 199 01/09 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 200 01/09 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 201 01/09 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 202 01/09 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 203 01/09 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 204 01/09 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 205 01/09 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 206 01/09 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 207 01/09 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 208 01/09 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 209 01/09 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 210 01/09 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 211 01/09 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 212 01/09 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 213 01/09 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 214 01/09 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 215 01/09 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 216 01/09 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 217 01/10 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 218 01/10 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 219 01/10 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 220 01/10 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 221 01/10 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 222 01/10 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 223 01/10 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 224 01/10 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 225 01/10 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 226 01/10 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 227 01/10 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 228 01/10 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 229 01/10 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 230 01/10 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 231 01/10 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 232 01/10 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 233 01/10 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 234 01/10 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 235 01/10 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 236 01/10 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 237 01/10 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 238 01/10 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 239 01/10 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 240 01/10 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 241 01/11 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 242 01/11 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 243 01/11 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 244 01/11 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 245 01/11 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 246 01/11 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 247 01/11 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 248 01/11 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 249 01/11 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 250 01/11 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 251 01/11 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 252 01/11 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 253 01/11 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 254 01/11 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 255 01/11 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 256 01/11 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 257 01/11 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 258 01/11 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 259 01/11 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 260 01/11 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 261 01/11 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 262 01/11 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 263 01/11 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 264 01/11 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 265 01/12 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 266 01/12 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 267 01/12 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 268 01/12 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 269 01/12 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 270 01/12 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 271 01/12 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 272 01/12 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 273 01/12 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 274 01/12 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 275 01/12 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 276 01/12 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 277 01/12 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 278 01/12 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 279 01/12 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 280 01/12 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 281 01/12 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 282 01/12 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 283 01/12 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 284 01/12 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 285 01/12 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 286 01/12 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 287 01/12 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 288 01/12 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 289 01/13 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 290 01/13 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 291 01/13 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 292 01/13 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 293 01/13 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 294 01/13 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 295 01/13 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 296 01/13 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 297 01/13 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 298 01/13 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 299 01/13 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 300 01/13 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 301 01/13 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 302 01/13 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 303 01/13 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 304 01/13 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 305 01/13 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 306 01/13 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 307 01/13 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 308 01/13 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 309 01/13 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 310 01/13 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 311 01/13 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 312 01/13 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 313 01/14 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 314 01/14 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 315 01/14 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 316 01/14 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 317 01/14 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 318 01/14 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 319 01/14 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 320 01/14 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 321 01/14 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 322 01/14 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 323 01/14 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 324 01/14 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 325 01/14 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 326 01/14 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 327 01/14 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 328 01/14 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 329 01/14 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 330 01/14 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 331 01/14 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 332 01/14 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 333 01/14 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 334 01/14 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 335 01/14 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 336 01/14 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 1 01/01 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 2 01/01 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 3 01/01 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 4 01/01 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 5 01/01 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 6 01/01 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 7 01/01 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 8 01/01 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 9 01/01 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 10 01/01 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 11 01/01 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 12 01/01 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 13 01/01 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 14 01/01 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 15 01/01 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 16 01/01 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 17 01/01 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 18 01/01 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 19 01/01 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 20 01/01 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 21 01/01 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 22 01/01 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 23 01/01 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 24 01/01 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 25 01/02 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 26 01/02 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 27 01/02 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 28 01/02 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 29 01/02 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 30 01/02 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 31 01/02 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 32 01/02 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 33 01/02 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 34 01/02 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 35 01/02 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 36 01/02 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 37 01/02 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 38 01/02 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 39 01/02 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 40 01/02 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 41 01/02 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 42 01/02 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 43 01/02 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 44 01/02 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 45 01/02 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 46 01/02 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 47 01/02 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 48 01/02 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 49 01/03 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 50 01/03 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 51 01/03 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 52 01/03 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 53 01/03 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 54 01/03 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 55 01/03 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 56 01/03 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 57 01/03 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 58 01/03 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 59 01/03 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 60 01/03 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 61 01/03 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 62 01/03 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 63 01/03 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 64 01/03 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 65 01/03 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 66 01/03 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 67 01/03 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 68 01/03 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 69 01/03 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 70 01/03 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 71 01/03 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 72 01/03 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 73 01/04 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 74 01/04 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 75 01/04 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 76 01/04 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 77 01/04 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 78 01/04 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 79 01/04 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 80 01/04 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 81 01/04 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 82 01/04 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 83 01/04 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 84 01/04 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 85 01/04 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 86 01/04 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 87 01/04 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 88 01/04 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 89 01/04 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 90 01/04 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 91 01/04 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 92 01/04 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 93 01/04 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 94 01/04 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 95 01/04 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 96 01/04 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 97 01/05 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 98 01/05 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 99 01/05 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 100 01/05 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 101 01/05 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 102 01/05 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 103 01/05 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 104 01/05 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 105 01/05 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 106 01/05 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 107 01/05 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 108 01/05 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 109 01/05 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 110 01/05 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 111 01/05 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 112 01/05 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 113 01/05 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 114 01/05 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 115 01/05 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 116 01/05 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 117 01/05 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 118 01/05 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 119 01/05 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 120 01/05 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 121 01/06 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 122 01/06 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 123 01/06 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 124 01/06 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 125 01/06 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 126 01/06 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 127 01/06 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 128 01/06 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 129 01/06 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 130 01/06 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 131 01/06 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 132 01/06 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 133 01/06 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 134 01/06 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 135 01/06 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 136 01/06 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 137 01/06 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 138 01/06 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 139 01/06 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 140 01/06 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 141 01/06 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 142 01/06 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 143 01/06 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 144 01/06 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 145 01/07 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 146 01/07 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 147 01/07 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 148 01/07 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 149 01/07 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 150 01/07 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 151 01/07 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 152 01/07 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 153 01/07 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 154 01/07 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 155 01/07 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 156 01/07 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 157 01/07 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 158 01/07 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 159 01/07 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 160 01/07 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 161 01/07 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 162 01/07 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 163 01/07 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 164 01/07 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 165 01/07 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 166 01/07 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 167 01/07 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 168 01/07 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 169 01/08 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 170 01/08 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 171 01/08 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 172 01/08 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 173 01/08 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 174 01/08 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 175 01/08 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 176 01/08 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 177 01/08 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 178 01/08 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 179 01/08 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 180 01/08 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 181 01/08 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 182 01/08 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 183 01/08 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 184 01/08 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 185 01/08 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 186 01/08 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 187 01/08 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 188 01/08 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 189 01/08 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 190 01/08 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 191 01/08 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 192 01/08 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 193 01/09 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 194 01/09 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 195 01/09 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 196 01/09 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 197 01/09 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 198 01/09 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 199 01/09 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 200 01/09 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 201 01/09 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 202 01/09 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 203 01/09 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 204 01/09 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 205 01/09 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 206 01/09 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 207 01/09 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 208 01/09 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 209 01/09 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 210 01/09 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 211 01/09 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 212 01/09 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 213 01/09 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 214 01/09 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 215 01/09 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 216 01/09 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 217 01/10 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 218 01/10 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 219 01/10 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 220 01/10 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 221 01/10 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 222 01/10 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 223 01/10 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 224 01/10 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 225 01/10 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 226 01/10 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 227 01/10 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 228 01/10 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 229 01/10 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 230 01/10 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 231 01/10 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 232 01/10 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 233 01/10 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 234 01/10 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 235 01/10 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 236 01/10 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 237 01/10 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 238 01/10 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 239 01/10 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 240 01/10 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 241 01/11 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 242 01/11 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 243 01/11 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 244 01/11 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 245 01/11 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 246 01/11 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 247 01/11 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 248 01/11 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 249 01/11 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 250 01/11 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 251 01/11 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 252 01/11 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 253 01/11 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 254 01/11 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 255 01/11 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 256 01/11 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 257 01/11 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 258 01/11 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 259 01/11 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 260 01/11 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 261 01/11 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 262 01/11 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 263 01/11 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 264 01/11 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 265 01/12 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 266 01/12 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 267 01/12 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 268 01/12 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 269 01/12 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 270 01/12 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 271 01/12 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 272 01/12 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 273 01/12 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 274 01/12 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 275 01/12 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 276 01/12 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 277 01/12 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 278 01/12 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 279 01/12 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 280 01/12 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 281 01/12 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 282 01/12 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 283 01/12 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 284 01/12 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 285 01/12 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 286 01/12 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 287 01/12 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 288 01/12 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 289 01/13 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 290 01/13 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 291 01/13 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 292 01/13 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 293 01/13 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 294 01/13 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 295 01/13 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 296 01/13 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 297 01/13 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 298 01/13 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 299 01/13 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 300 01/13 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 301 01/13 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 302 01/13 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 303 01/13 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 304 01/13 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 305 01/13 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 306 01/13 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 307 01/13 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 308 01/13 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 309 01/13 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 310 01/13 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 311 01/13 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 312 01/13 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 313 01/14 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 314 01/14 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 315 01/14 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 316 01/14 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 317 01/14 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 318 01/14 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 319 01/14 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 320 01/14 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 321 01/14 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 322 01/14 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 323 01/14 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 324 01/14 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 325 01/14 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 326 01/14 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 327 01/14 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 328 01/14 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 329 01/14 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 330 01/14 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 331 01/14 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 332 01/14 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 333 01/14 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 334 01/14 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 335 01/14 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 336 01/14 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 1 01/01 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 2 01/01 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 3 01/01 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 4 01/01 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 5 01/01 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 6 01/01 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 7 01/01 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 8 01/01 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 9 01/01 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 10 01/01 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 11 01/01 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 12 01/01 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 13 01/01 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 14 01/01 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 15 01/01 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 16 01/01 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 17 01/01 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 18 01/01 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 19 01/01 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 20 01/01 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 21 01/01 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 22 01/01 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 23 01/01 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 24 01/01 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 25 01/02 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 26 01/02 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 27 01/02 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 28 01/02 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 29 01/02 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 30 01/02 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 31 01/02 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 32 01/02 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 33 01/02 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 34 01/02 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 35 01/02 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 36 01/02 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 37 01/02 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 38 01/02 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 39 01/02 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 40 01/02 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 41 01/02 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 42 01/02 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 43 01/02 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 44 01/02 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 45 01/02 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 46 01/02 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 47 01/02 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 48 01/02 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 49 01/03 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 50 01/03 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 51 01/03 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 52 01/03 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 53 01/03 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 54 01/03 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 55 01/03 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 56 01/03 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 57 01/03 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 58 01/03 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 59 01/03 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 60 01/03 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 61 01/03 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 62 01/03 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 63 01/03 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 64 01/03 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 65 01/03 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 66 01/03 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 67 01/03 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 68 01/03 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 69 01/03 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 70 01/03 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 71 01/03 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 72 01/03 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 73 01/04 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 74 01/04 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 75 01/04 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 76 01/04 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 77 01/04 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 78 01/04 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 79 01/04 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 80 01/04 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 81 01/04 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 82 01/04 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 83 01/04 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 84 01/04 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 85 01/04 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 86 01/04 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 87 01/04 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 88 01/04 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 89 01/04 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 90 01/04 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 91 01/04 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 92 01/04 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 93 01/04 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 94 01/04 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 95 01/04 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 96 01/04 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 97 01/05 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 98 01/05 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 99 01/05 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 100 01/05 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 101 01/05 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 102 01/05 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 103 01/05 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 104 01/05 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 105 01/05 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 106 01/05 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 107 01/05 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 108 01/05 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 109 01/05 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 110 01/05 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 111 01/05 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 112 01/05 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 113 01/05 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 114 01/05 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 115 01/05 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 116 01/05 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 117 01/05 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 118 01/05 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 119 01/05 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 120 01/05 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 121 01/06 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 122 01/06 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 123 01/06 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 124 01/06 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 125 01/06 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 126 01/06 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 127 01/06 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 128 01/06 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 129 01/06 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 130 01/06 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 131 01/06 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 132 01/06 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 133 01/06 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 134 01/06 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 135 01/06 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 136 01/06 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 137 01/06 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 138 01/06 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 139 01/06 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 140 01/06 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 141 01/06 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 142 01/06 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 143 01/06 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 144 01/06 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 145 01/07 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 146 01/07 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 147 01/07 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 148 01/07 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 149 01/07 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 150 01/07 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 151 01/07 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 152 01/07 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 153 01/07 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 154 01/07 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 155 01/07 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 156 01/07 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 157 01/07 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 158 01/07 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 159 01/07 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 160 01/07 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 161 01/07 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 162 01/07 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 163 01/07 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 164 01/07 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 165 01/07 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 166 01/07 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 167 01/07 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 168 01/07 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 169 01/08 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 170 01/08 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 171 01/08 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 172 01/08 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 173 01/08 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 174 01/08 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 175 01/08 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 176 01/08 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 177 01/08 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 178 01/08 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 179 01/08 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 180 01/08 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 181 01/08 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 182 01/08 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 183 01/08 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 184 01/08 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 185 01/08 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 186 01/08 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 187 01/08 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 188 01/08 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 189 01/08 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 190 01/08 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 191 01/08 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 192 01/08 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 193 01/09 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 194 01/09 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 195 01/09 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 196 01/09 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 197 01/09 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 198 01/09 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 199 01/09 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 200 01/09 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 201 01/09 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 202 01/09 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 203 01/09 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 204 01/09 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 205 01/09 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 206 01/09 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 207 01/09 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 208 01/09 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 209 01/09 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 210 01/09 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 211 01/09 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 212 01/09 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 213 01/09 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 214 01/09 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 215 01/09 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 216 01/09 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 217 01/10 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 218 01/10 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 219 01/10 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 220 01/10 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 221 01/10 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 222 01/10 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 223 01/10 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 224 01/10 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 225 01/10 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 226 01/10 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 227 01/10 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 228 01/10 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 229 01/10 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 230 01/10 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 231 01/10 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 232 01/10 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 233 01/10 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 234 01/10 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 235 01/10 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 236 01/10 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 237 01/10 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 238 01/10 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 239 01/10 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 240 01/10 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 241 01/11 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 242 01/11 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 243 01/11 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 244 01/11 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 245 01/11 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 246 01/11 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 247 01/11 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 248 01/11 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 249 01/11 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 250 01/11 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 251 01/11 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 252 01/11 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 253 01/11 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 254 01/11 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 255 01/11 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 256 01/11 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 257 01/11 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 258 01/11 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 259 01/11 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 260 01/11 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 261 01/11 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 262 01/11 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 263 01/11 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 264 01/11 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 265 01/12 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 266 01/12 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 267 01/12 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 268 01/12 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 269 01/12 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 270 01/12 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 271 01/12 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 272 01/12 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 273 01/12 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 274 01/12 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 275 01/12 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 276 01/12 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 277 01/12 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 278 01/12 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 279 01/12 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 280 01/12 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 281 01/12 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 282 01/12 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 283 01/12 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 284 01/12 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 285 01/12 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 286 01/12 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 287 01/12 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 288 01/12 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 289 01/13 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 290 01/13 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 291 01/13 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 292 01/13 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 293 01/13 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 294 01/13 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 295 01/13 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 296 01/13 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 297 01/13 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 298 01/13 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 299 01/13 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 300 01/13 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 301 01/13 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 302 01/13 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 303 01/13 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 304 01/13 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 305 01/13 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 306 01/13 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 307 01/13 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 308 01/13 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 309 01/13 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 310 01/13 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 311 01/13 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 312 01/13 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 313 01/14 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 314 01/14 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 315 01/14 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 316 01/14 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 317 01/14 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 318 01/14 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 319 01/14 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 320 01/14 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 321 01/14 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 322 01/14 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 323 01/14 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 324 01/14 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 325 01/14 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 326 01/14 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 327 01/14 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 328 01/14 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 329 01/14 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 330 01/14 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 331 01/14 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 332 01/14 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 333 01/14 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 334 01/14 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 335 01/14 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 2 336 01/14 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 1 01/01 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 2 01/01 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 3 01/01 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 4 01/01 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 5 01/01 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 6 01/01 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 7 01/01 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 8 01/01 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 9 01/01 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 10 01/01 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 11 01/01 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 12 01/01 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 13 01/01 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 14 01/01 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 15 01/01 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 16 01/01 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 17 01/01 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 18 01/01 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 19 01/01 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 20 01/01 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 21 01/01 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 22 01/01 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 23 01/01 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 24 01/01 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 25 01/02 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 26 01/02 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 27 01/02 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 28 01/02 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 29 01/02 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 30 01/02 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 31 01/02 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 32 01/02 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 33 01/02 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 34 01/02 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 35 01/02 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 36 01/02 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 37 01/02 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 38 01/02 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 39 01/02 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 40 01/02 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 41 01/02 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 42 01/02 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 43 01/02 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 44 01/02 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 45 01/02 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 46 01/02 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 47 01/02 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 48 01/02 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 49 01/03 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 50 01/03 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 51 01/03 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 52 01/03 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 53 01/03 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 54 01/03 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 55 01/03 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 56 01/03 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 57 01/03 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 58 01/03 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 59 01/03 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 60 01/03 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 61 01/03 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 62 01/03 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 63 01/03 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 64 01/03 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 65 01/03 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 66 01/03 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 67 01/03 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 68 01/03 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 69 01/03 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 70 01/03 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 71 01/03 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 72 01/03 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 73 01/04 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 74 01/04 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 75 01/04 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 76 01/04 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 77 01/04 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 78 01/04 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 79 01/04 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 80 01/04 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 81 01/04 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 82 01/04 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 83 01/04 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 84 01/04 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 85 01/04 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 86 01/04 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 87 01/04 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 88 01/04 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 89 01/04 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 90 01/04 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 91 01/04 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 92 01/04 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 93 01/04 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 94 01/04 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 95 01/04 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 96 01/04 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 97 01/05 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 98 01/05 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 99 01/05 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 100 01/05 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 101 01/05 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 102 01/05 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 103 01/05 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 104 01/05 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 105 01/05 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 106 01/05 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 107 01/05 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 108 01/05 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 109 01/05 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 110 01/05 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 111 01/05 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 112 01/05 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 113 01/05 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 114 01/05 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 115 01/05 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 116 01/05 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 117 01/05 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 118 01/05 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 119 01/05 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 120 01/05 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 121 01/06 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 122 01/06 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 123 01/06 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 124 01/06 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 125 01/06 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 126 01/06 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 127 01/06 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 128 01/06 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 129 01/06 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 130 01/06 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 131 01/06 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 132 01/06 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 133 01/06 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 134 01/06 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 135 01/06 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 136 01/06 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 137 01/06 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 138 01/06 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 139 01/06 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 140 01/06 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 141 01/06 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 142 01/06 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 143 01/06 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 144 01/06 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 145 01/07 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 146 01/07 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 147 01/07 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 148 01/07 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 149 01/07 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 150 01/07 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 151 01/07 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 152 01/07 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 153 01/07 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 154 01/07 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 155 01/07 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 156 01/07 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 157 01/07 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 158 01/07 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 159 01/07 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 160 01/07 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 161 01/07 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 162 01/07 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 163 01/07 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 164 01/07 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 165 01/07 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 166 01/07 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 167 01/07 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 168 01/07 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 169 01/08 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 170 01/08 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 171 01/08 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 172 01/08 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 173 01/08 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 174 01/08 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 175 01/08 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 176 01/08 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 177 01/08 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 178 01/08 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 179 01/08 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 180 01/08 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 181 01/08 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 182 01/08 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 183 01/08 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 184 01/08 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 185 01/08 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 186 01/08 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 187 01/08 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 188 01/08 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 189 01/08 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 190 01/08 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 191 01/08 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 192 01/08 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 193 01/09 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 194 01/09 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 195 01/09 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 196 01/09 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 197 01/09 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 198 01/09 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 199 01/09 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 200 01/09 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 201 01/09 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 202 01/09 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 203 01/09 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 204 01/09 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 205 01/09 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 206 01/09 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 207 01/09 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 208 01/09 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 209 01/09 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 210 01/09 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 211 01/09 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 212 01/09 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 213 01/09 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 214 01/09 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 215 01/09 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 216 01/09 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 217 01/10 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 218 01/10 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 219 01/10 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 220 01/10 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 221 01/10 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 222 01/10 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 223 01/10 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 224 01/10 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 225 01/10 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 226 01/10 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 227 01/10 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 228 01/10 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 229 01/10 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 230 01/10 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 231 01/10 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 232 01/10 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 233 01/10 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 234 01/10 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 235 01/10 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 236 01/10 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 237 01/10 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 238 01/10 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 239 01/10 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 240 01/10 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 241 01/11 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 242 01/11 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 243 01/11 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 244 01/11 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 245 01/11 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 246 01/11 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 247 01/11 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 248 01/11 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 249 01/11 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 250 01/11 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 251 01/11 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 252 01/11 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 253 01/11 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 254 01/11 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 255 01/11 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 256 01/11 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 257 01/11 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 258 01/11 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 259 01/11 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 260 01/11 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 261 01/11 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 262 01/11 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 263 01/11 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 264 01/11 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 265 01/12 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 266 01/12 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 267 01/12 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 268 01/12 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 269 01/12 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 270 01/12 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 271 01/12 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 272 01/12 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 273 01/12 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 274 01/12 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 275 01/12 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 276 01/12 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 277 01/12 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 278 01/12 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 279 01/12 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 280 01/12 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 281 01/12 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 282 01/12 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 283 01/12 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 284 01/12 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 285 01/12 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 286 01/12 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 287 01/12 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 288 01/12 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 289 01/13 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 290 01/13 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 291 01/13 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 292 01/13 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 293 01/13 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 294 01/13 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 295 01/13 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 296 01/13 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 297 01/13 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 298 01/13 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 299 01/13 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 300 01/13 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 301 01/13 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 302 01/13 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 303 01/13 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 304 01/13 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 305 01/13 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 306 01/13 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 307 01/13 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 308 01/13 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 309 01/13 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 310 01/13 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 311 01/13 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 312 01/13 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 313 01/14 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 314 01/14 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 315 01/14 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 316 01/14 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 317 01/14 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 318 01/14 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 319 01/14 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 320 01/14 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 321 01/14 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 322 01/14 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 323 01/14 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 324 01/14 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 325 01/14 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 326 01/14 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 327 01/14 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 328 01/14 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 329 01/14 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 330 01/14 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 331 01/14 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 332 01/14 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 333 01/14 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 334 01/14 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 335 01/14 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 2 336 01/14 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 1 01/01 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 2 01/01 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 3 01/01 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 4 01/01 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 5 01/01 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 6 01/01 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 7 01/01 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 8 01/01 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 9 01/01 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 10 01/01 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 11 01/01 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 12 01/01 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 13 01/01 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 14 01/01 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 15 01/01 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 16 01/01 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 17 01/01 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 18 01/01 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 19 01/01 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 20 01/01 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 21 01/01 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 22 01/01 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 23 01/01 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 24 01/01 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 25 01/02 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 26 01/02 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 27 01/02 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 28 01/02 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 29 01/02 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 30 01/02 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 31 01/02 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 32 01/02 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 33 01/02 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 34 01/02 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 35 01/02 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 36 01/02 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 37 01/02 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 38 01/02 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 39 01/02 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 40 01/02 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 41 01/02 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 42 01/02 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 43 01/02 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 44 01/02 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 45 01/02 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 46 01/02 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 47 01/02 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 48 01/02 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 49 01/03 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 50 01/03 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 51 01/03 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 52 01/03 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 53 01/03 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 54 01/03 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 55 01/03 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 56 01/03 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 57 01/03 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 58 01/03 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 59 01/03 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 60 01/03 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 61 01/03 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 62 01/03 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 63 01/03 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 64 01/03 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 65 01/03 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 66 01/03 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 67 01/03 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 68 01/03 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 69 01/03 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 70 01/03 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 71 01/03 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 72 01/03 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 73 01/04 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 74 01/04 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 75 01/04 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 76 01/04 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 77 01/04 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 78 01/04 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 79 01/04 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 80 01/04 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 81 01/04 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 82 01/04 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 83 01/04 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 84 01/04 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 85 01/04 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 86 01/04 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 87 01/04 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 88 01/04 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 89 01/04 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 90 01/04 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 91 01/04 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 92 01/04 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 93 01/04 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 94 01/04 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 95 01/04 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 96 01/04 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 97 01/05 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 98 01/05 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 99 01/05 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 100 01/05 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 101 01/05 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 102 01/05 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 103 01/05 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 104 01/05 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 105 01/05 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 106 01/05 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 107 01/05 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 108 01/05 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 109 01/05 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 110 01/05 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 111 01/05 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 112 01/05 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 113 01/05 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 114 01/05 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 115 01/05 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 116 01/05 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 117 01/05 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 118 01/05 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 119 01/05 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 120 01/05 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 121 01/06 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 122 01/06 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 123 01/06 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 124 01/06 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 125 01/06 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 126 01/06 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 127 01/06 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 128 01/06 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 129 01/06 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 130 01/06 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 131 01/06 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 132 01/06 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 133 01/06 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 134 01/06 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 135 01/06 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 136 01/06 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 137 01/06 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 138 01/06 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 139 01/06 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 140 01/06 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 141 01/06 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 142 01/06 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 143 01/06 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 144 01/06 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 145 01/07 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 146 01/07 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 147 01/07 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 148 01/07 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 149 01/07 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 150 01/07 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 151 01/07 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 152 01/07 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 153 01/07 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 154 01/07 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 155 01/07 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 156 01/07 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 157 01/07 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 158 01/07 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 159 01/07 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 160 01/07 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 161 01/07 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 162 01/07 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 163 01/07 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 164 01/07 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 165 01/07 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 166 01/07 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 167 01/07 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 168 01/07 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 169 01/08 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 170 01/08 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 171 01/08 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 172 01/08 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 173 01/08 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 174 01/08 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 175 01/08 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 176 01/08 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 177 01/08 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 178 01/08 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 179 01/08 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 180 01/08 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 181 01/08 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 182 01/08 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 183 01/08 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 184 01/08 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 185 01/08 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 186 01/08 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 187 01/08 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 188 01/08 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 189 01/08 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 190 01/08 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 191 01/08 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 192 01/08 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 193 01/09 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 194 01/09 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 195 01/09 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 196 01/09 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 197 01/09 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 198 01/09 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 199 01/09 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 200 01/09 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 201 01/09 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 202 01/09 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 203 01/09 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 204 01/09 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 205 01/09 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 206 01/09 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 207 01/09 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 208 01/09 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 209 01/09 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 210 01/09 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 211 01/09 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 212 01/09 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 213 01/09 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 214 01/09 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 215 01/09 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 216 01/09 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 217 01/10 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 218 01/10 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 219 01/10 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 220 01/10 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 221 01/10 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 222 01/10 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 223 01/10 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 224 01/10 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 225 01/10 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 226 01/10 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 227 01/10 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 228 01/10 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 229 01/10 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 230 01/10 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 231 01/10 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 232 01/10 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 233 01/10 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 234 01/10 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 235 01/10 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 236 01/10 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 237 01/10 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 238 01/10 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 239 01/10 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 240 01/10 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 241 01/11 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 242 01/11 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 243 01/11 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 244 01/11 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 245 01/11 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 246 01/11 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 247 01/11 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 248 01/11 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 249 01/11 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 250 01/11 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 251 01/11 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 252 01/11 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 253 01/11 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 254 01/11 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 255 01/11 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 256 01/11 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 257 01/11 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 258 01/11 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 259 01/11 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 260 01/11 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 261 01/11 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 262 01/11 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 263 01/11 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 264 01/11 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 265 01/12 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 266 01/12 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 267 01/12 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 268 01/12 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 269 01/12 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 270 01/12 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 271 01/12 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 272 01/12 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 273 01/12 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 274 01/12 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 275 01/12 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 276 01/12 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 277 01/12 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 278 01/12 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 279 01/12 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 280 01/12 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 281 01/12 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 282 01/12 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 283 01/12 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 284 01/12 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 285 01/12 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 286 01/12 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 287 01/12 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 288 01/12 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 289 01/13 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 290 01/13 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 291 01/13 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 292 01/13 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 293 01/13 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 294 01/13 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 295 01/13 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 296 01/13 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 297 01/13 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 298 01/13 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 299 01/13 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 300 01/13 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 301 01/13 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 302 01/13 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 303 01/13 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 304 01/13 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 305 01/13 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 306 01/13 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 307 01/13 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 308 01/13 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 309 01/13 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 310 01/13 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 311 01/13 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 312 01/13 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 313 01/14 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 314 01/14 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 315 01/14 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 316 01/14 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 317 01/14 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 318 01/14 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 319 01/14 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 320 01/14 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 321 01/14 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 322 01/14 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 323 01/14 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 324 01/14 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 325 01/14 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 326 01/14 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 327 01/14 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 328 01/14 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 329 01/14 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 330 01/14 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 331 01/14 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 332 01/14 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 333 01/14 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 334 01/14 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 335 01/14 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 2 336 01/14 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 diff --git a/tests/integration/raw_studies_blueprint/assets/aggregate_links_raw_data/test-02.result.tsv b/tests/integration/raw_studies_blueprint/assets/aggregate_links_raw_data/test-02.result.tsv new file mode 100644 index 0000000000..ff2416e246 --- /dev/null +++ b/tests/integration/raw_studies_blueprint/assets/aggregate_links_raw_data/test-02.result.tsv @@ -0,0 +1,1009 @@ +link mcYear timeId time FLOW LIN. UCAP LIN. LOOP FLOW FLOW QUAD. CONG. FEE (ALG.) CONG. FEE (ABS.) MARG. COST CONG. PROB + CONG. PROB - HURDLE COST +de - fr 1 1 01/01 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 2 01/01 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 3 01/01 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 4 01/01 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 5 01/01 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 6 01/01 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 7 01/01 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 8 01/01 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 9 01/01 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 10 01/01 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 11 01/01 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 12 01/01 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 13 01/01 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 14 01/01 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 15 01/01 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 16 01/01 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 17 01/01 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 18 01/01 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 19 01/01 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 20 01/01 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 21 01/01 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 22 01/01 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 23 01/01 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 24 01/01 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 25 01/02 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 26 01/02 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 27 01/02 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 28 01/02 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 29 01/02 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 30 01/02 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 31 01/02 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 32 01/02 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 33 01/02 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 34 01/02 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 35 01/02 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 36 01/02 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 37 01/02 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 38 01/02 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 39 01/02 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 40 01/02 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 41 01/02 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 42 01/02 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 43 01/02 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 44 01/02 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 45 01/02 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 46 01/02 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 47 01/02 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 48 01/02 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 49 01/03 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 50 01/03 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 51 01/03 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 52 01/03 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 53 01/03 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 54 01/03 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 55 01/03 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 56 01/03 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 57 01/03 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 58 01/03 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 59 01/03 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 60 01/03 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 61 01/03 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 62 01/03 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 63 01/03 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 64 01/03 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 65 01/03 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 66 01/03 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 67 01/03 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 68 01/03 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 69 01/03 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 70 01/03 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 71 01/03 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 72 01/03 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 73 01/04 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 74 01/04 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 75 01/04 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 76 01/04 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 77 01/04 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 78 01/04 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 79 01/04 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 80 01/04 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 81 01/04 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 82 01/04 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 83 01/04 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 84 01/04 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 85 01/04 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 86 01/04 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 87 01/04 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 88 01/04 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 89 01/04 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 90 01/04 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 91 01/04 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 92 01/04 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 93 01/04 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 94 01/04 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 95 01/04 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 96 01/04 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 97 01/05 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 98 01/05 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 99 01/05 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 100 01/05 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 101 01/05 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 102 01/05 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 103 01/05 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 104 01/05 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 105 01/05 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 106 01/05 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 107 01/05 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 108 01/05 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 109 01/05 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 110 01/05 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 111 01/05 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 112 01/05 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 113 01/05 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 114 01/05 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 115 01/05 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 116 01/05 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 117 01/05 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 118 01/05 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 119 01/05 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 120 01/05 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 121 01/06 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 122 01/06 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 123 01/06 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 124 01/06 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 125 01/06 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 126 01/06 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 127 01/06 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 128 01/06 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 129 01/06 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 130 01/06 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 131 01/06 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 132 01/06 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 133 01/06 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 134 01/06 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 135 01/06 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 136 01/06 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 137 01/06 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 138 01/06 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 139 01/06 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 140 01/06 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 141 01/06 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 142 01/06 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 143 01/06 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 144 01/06 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 145 01/07 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 146 01/07 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 147 01/07 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 148 01/07 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 149 01/07 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 150 01/07 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 151 01/07 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 152 01/07 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 153 01/07 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 154 01/07 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 155 01/07 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 156 01/07 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 157 01/07 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 158 01/07 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 159 01/07 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 160 01/07 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 161 01/07 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 162 01/07 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 163 01/07 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 164 01/07 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 165 01/07 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 166 01/07 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 167 01/07 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 168 01/07 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 169 01/08 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 170 01/08 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 171 01/08 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 172 01/08 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 173 01/08 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 174 01/08 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 175 01/08 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 176 01/08 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 177 01/08 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 178 01/08 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 179 01/08 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 180 01/08 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 181 01/08 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 182 01/08 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 183 01/08 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 184 01/08 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 185 01/08 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 186 01/08 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 187 01/08 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 188 01/08 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 189 01/08 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 190 01/08 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 191 01/08 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 192 01/08 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 193 01/09 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 194 01/09 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 195 01/09 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 196 01/09 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 197 01/09 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 198 01/09 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 199 01/09 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 200 01/09 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 201 01/09 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 202 01/09 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 203 01/09 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 204 01/09 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 205 01/09 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 206 01/09 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 207 01/09 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 208 01/09 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 209 01/09 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 210 01/09 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 211 01/09 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 212 01/09 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 213 01/09 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 214 01/09 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 215 01/09 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 216 01/09 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 217 01/10 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 218 01/10 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 219 01/10 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 220 01/10 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 221 01/10 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 222 01/10 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 223 01/10 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 224 01/10 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 225 01/10 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 226 01/10 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 227 01/10 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 228 01/10 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 229 01/10 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 230 01/10 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 231 01/10 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 232 01/10 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 233 01/10 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 234 01/10 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 235 01/10 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 236 01/10 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 237 01/10 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 238 01/10 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 239 01/10 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 240 01/10 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 241 01/11 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 242 01/11 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 243 01/11 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 244 01/11 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 245 01/11 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 246 01/11 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 247 01/11 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 248 01/11 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 249 01/11 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 250 01/11 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 251 01/11 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 252 01/11 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 253 01/11 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 254 01/11 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 255 01/11 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 256 01/11 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 257 01/11 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 258 01/11 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 259 01/11 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 260 01/11 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 261 01/11 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 262 01/11 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 263 01/11 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 264 01/11 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 265 01/12 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 266 01/12 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 267 01/12 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 268 01/12 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 269 01/12 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 270 01/12 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 271 01/12 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 272 01/12 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 273 01/12 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 274 01/12 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 275 01/12 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 276 01/12 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 277 01/12 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 278 01/12 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 279 01/12 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 280 01/12 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 281 01/12 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 282 01/12 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 283 01/12 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 284 01/12 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 285 01/12 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 286 01/12 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 287 01/12 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 288 01/12 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 289 01/13 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 290 01/13 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 291 01/13 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 292 01/13 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 293 01/13 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 294 01/13 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 295 01/13 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 296 01/13 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 297 01/13 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 298 01/13 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 299 01/13 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 300 01/13 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 301 01/13 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 302 01/13 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 303 01/13 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 304 01/13 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 305 01/13 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 306 01/13 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 307 01/13 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 308 01/13 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 309 01/13 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 310 01/13 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 311 01/13 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 312 01/13 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 313 01/14 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 314 01/14 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 315 01/14 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 316 01/14 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 317 01/14 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 318 01/14 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 319 01/14 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 320 01/14 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 321 01/14 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 322 01/14 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 323 01/14 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 324 01/14 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 325 01/14 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 326 01/14 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 327 01/14 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 328 01/14 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 329 01/14 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 330 01/14 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 331 01/14 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 332 01/14 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 333 01/14 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 334 01/14 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 335 01/14 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +de - fr 1 336 01/14 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 1 01/01 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 2 01/01 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 3 01/01 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 4 01/01 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 5 01/01 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 6 01/01 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 7 01/01 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 8 01/01 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 9 01/01 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 10 01/01 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 11 01/01 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 12 01/01 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 13 01/01 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 14 01/01 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 15 01/01 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 16 01/01 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 17 01/01 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 18 01/01 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 19 01/01 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 20 01/01 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 21 01/01 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 22 01/01 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 23 01/01 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 24 01/01 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 25 01/02 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 26 01/02 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 27 01/02 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 28 01/02 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 29 01/02 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 30 01/02 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 31 01/02 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 32 01/02 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 33 01/02 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 34 01/02 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 35 01/02 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 36 01/02 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 37 01/02 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 38 01/02 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 39 01/02 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 40 01/02 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 41 01/02 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 42 01/02 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 43 01/02 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 44 01/02 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 45 01/02 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 46 01/02 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 47 01/02 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 48 01/02 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 49 01/03 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 50 01/03 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 51 01/03 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 52 01/03 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 53 01/03 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 54 01/03 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 55 01/03 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 56 01/03 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 57 01/03 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 58 01/03 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 59 01/03 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 60 01/03 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 61 01/03 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 62 01/03 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 63 01/03 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 64 01/03 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 65 01/03 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 66 01/03 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 67 01/03 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 68 01/03 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 69 01/03 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 70 01/03 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 71 01/03 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 72 01/03 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 73 01/04 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 74 01/04 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 75 01/04 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 76 01/04 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 77 01/04 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 78 01/04 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 79 01/04 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 80 01/04 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 81 01/04 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 82 01/04 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 83 01/04 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 84 01/04 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 85 01/04 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 86 01/04 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 87 01/04 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 88 01/04 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 89 01/04 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 90 01/04 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 91 01/04 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 92 01/04 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 93 01/04 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 94 01/04 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 95 01/04 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 96 01/04 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 97 01/05 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 98 01/05 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 99 01/05 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 100 01/05 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 101 01/05 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 102 01/05 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 103 01/05 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 104 01/05 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 105 01/05 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 106 01/05 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 107 01/05 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 108 01/05 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 109 01/05 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 110 01/05 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 111 01/05 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 112 01/05 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 113 01/05 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 114 01/05 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 115 01/05 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 116 01/05 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 117 01/05 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 118 01/05 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 119 01/05 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 120 01/05 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 121 01/06 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 122 01/06 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 123 01/06 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 124 01/06 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 125 01/06 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 126 01/06 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 127 01/06 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 128 01/06 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 129 01/06 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 130 01/06 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 131 01/06 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 132 01/06 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 133 01/06 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 134 01/06 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 135 01/06 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 136 01/06 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 137 01/06 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 138 01/06 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 139 01/06 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 140 01/06 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 141 01/06 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 142 01/06 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 143 01/06 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 144 01/06 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 145 01/07 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 146 01/07 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 147 01/07 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 148 01/07 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 149 01/07 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 150 01/07 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 151 01/07 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 152 01/07 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 153 01/07 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 154 01/07 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 155 01/07 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 156 01/07 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 157 01/07 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 158 01/07 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 159 01/07 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 160 01/07 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 161 01/07 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 162 01/07 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 163 01/07 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 164 01/07 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 165 01/07 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 166 01/07 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 167 01/07 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 168 01/07 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 169 01/08 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 170 01/08 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 171 01/08 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 172 01/08 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 173 01/08 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 174 01/08 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 175 01/08 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 176 01/08 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 177 01/08 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 178 01/08 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 179 01/08 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 180 01/08 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 181 01/08 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 182 01/08 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 183 01/08 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 184 01/08 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 185 01/08 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 186 01/08 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 187 01/08 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 188 01/08 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 189 01/08 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 190 01/08 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 191 01/08 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 192 01/08 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 193 01/09 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 194 01/09 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 195 01/09 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 196 01/09 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 197 01/09 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 198 01/09 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 199 01/09 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 200 01/09 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 201 01/09 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 202 01/09 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 203 01/09 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 204 01/09 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 205 01/09 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 206 01/09 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 207 01/09 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 208 01/09 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 209 01/09 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 210 01/09 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 211 01/09 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 212 01/09 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 213 01/09 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 214 01/09 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 215 01/09 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 216 01/09 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 217 01/10 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 218 01/10 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 219 01/10 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 220 01/10 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 221 01/10 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 222 01/10 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 223 01/10 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 224 01/10 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 225 01/10 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 226 01/10 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 227 01/10 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 228 01/10 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 229 01/10 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 230 01/10 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 231 01/10 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 232 01/10 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 233 01/10 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 234 01/10 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 235 01/10 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 236 01/10 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 237 01/10 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 238 01/10 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 239 01/10 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 240 01/10 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 241 01/11 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 242 01/11 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 243 01/11 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 244 01/11 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 245 01/11 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 246 01/11 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 247 01/11 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 248 01/11 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 249 01/11 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 250 01/11 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 251 01/11 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 252 01/11 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 253 01/11 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 254 01/11 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 255 01/11 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 256 01/11 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 257 01/11 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 258 01/11 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 259 01/11 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 260 01/11 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 261 01/11 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 262 01/11 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 263 01/11 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 264 01/11 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 265 01/12 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 266 01/12 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 267 01/12 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 268 01/12 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 269 01/12 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 270 01/12 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 271 01/12 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 272 01/12 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 273 01/12 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 274 01/12 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 275 01/12 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 276 01/12 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 277 01/12 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 278 01/12 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 279 01/12 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 280 01/12 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 281 01/12 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 282 01/12 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 283 01/12 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 284 01/12 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 285 01/12 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 286 01/12 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 287 01/12 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 288 01/12 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 289 01/13 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 290 01/13 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 291 01/13 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 292 01/13 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 293 01/13 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 294 01/13 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 295 01/13 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 296 01/13 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 297 01/13 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 298 01/13 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 299 01/13 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 300 01/13 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 301 01/13 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 302 01/13 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 303 01/13 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 304 01/13 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 305 01/13 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 306 01/13 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 307 01/13 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 308 01/13 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 309 01/13 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 310 01/13 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 311 01/13 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 312 01/13 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 313 01/14 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 314 01/14 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 315 01/14 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 316 01/14 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 317 01/14 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 318 01/14 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 319 01/14 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 320 01/14 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 321 01/14 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 322 01/14 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 323 01/14 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 324 01/14 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 325 01/14 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 326 01/14 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 327 01/14 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 328 01/14 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 329 01/14 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 330 01/14 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 331 01/14 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 332 01/14 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 333 01/14 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 334 01/14 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 335 01/14 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +es - fr 1 336 01/14 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 1 01/01 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 2 01/01 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 3 01/01 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 4 01/01 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 5 01/01 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 6 01/01 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 7 01/01 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 8 01/01 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 9 01/01 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 10 01/01 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 11 01/01 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 12 01/01 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 13 01/01 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 14 01/01 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 15 01/01 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 16 01/01 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 17 01/01 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 18 01/01 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 19 01/01 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 20 01/01 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 21 01/01 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 22 01/01 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 23 01/01 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 24 01/01 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 25 01/02 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 26 01/02 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 27 01/02 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 28 01/02 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 29 01/02 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 30 01/02 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 31 01/02 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 32 01/02 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 33 01/02 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 34 01/02 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 35 01/02 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 36 01/02 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 37 01/02 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 38 01/02 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 39 01/02 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 40 01/02 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 41 01/02 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 42 01/02 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 43 01/02 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 44 01/02 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 45 01/02 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 46 01/02 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 47 01/02 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 48 01/02 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 49 01/03 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 50 01/03 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 51 01/03 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 52 01/03 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 53 01/03 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 54 01/03 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 55 01/03 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 56 01/03 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 57 01/03 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 58 01/03 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 59 01/03 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 60 01/03 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 61 01/03 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 62 01/03 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 63 01/03 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 64 01/03 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 65 01/03 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 66 01/03 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 67 01/03 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 68 01/03 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 69 01/03 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 70 01/03 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 71 01/03 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 72 01/03 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 73 01/04 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 74 01/04 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 75 01/04 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 76 01/04 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 77 01/04 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 78 01/04 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 79 01/04 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 80 01/04 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 81 01/04 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 82 01/04 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 83 01/04 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 84 01/04 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 85 01/04 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 86 01/04 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 87 01/04 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 88 01/04 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 89 01/04 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 90 01/04 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 91 01/04 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 92 01/04 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 93 01/04 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 94 01/04 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 95 01/04 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 96 01/04 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 97 01/05 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 98 01/05 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 99 01/05 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 100 01/05 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 101 01/05 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 102 01/05 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 103 01/05 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 104 01/05 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 105 01/05 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 106 01/05 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 107 01/05 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 108 01/05 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 109 01/05 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 110 01/05 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 111 01/05 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 112 01/05 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 113 01/05 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 114 01/05 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 115 01/05 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 116 01/05 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 117 01/05 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 118 01/05 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 119 01/05 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 120 01/05 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 121 01/06 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 122 01/06 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 123 01/06 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 124 01/06 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 125 01/06 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 126 01/06 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 127 01/06 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 128 01/06 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 129 01/06 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 130 01/06 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 131 01/06 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 132 01/06 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 133 01/06 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 134 01/06 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 135 01/06 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 136 01/06 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 137 01/06 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 138 01/06 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 139 01/06 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 140 01/06 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 141 01/06 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 142 01/06 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 143 01/06 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 144 01/06 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 145 01/07 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 146 01/07 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 147 01/07 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 148 01/07 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 149 01/07 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 150 01/07 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 151 01/07 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 152 01/07 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 153 01/07 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 154 01/07 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 155 01/07 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 156 01/07 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 157 01/07 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 158 01/07 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 159 01/07 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 160 01/07 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 161 01/07 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 162 01/07 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 163 01/07 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 164 01/07 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 165 01/07 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 166 01/07 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 167 01/07 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 168 01/07 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 169 01/08 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 170 01/08 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 171 01/08 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 172 01/08 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 173 01/08 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 174 01/08 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 175 01/08 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 176 01/08 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 177 01/08 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 178 01/08 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 179 01/08 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 180 01/08 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 181 01/08 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 182 01/08 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 183 01/08 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 184 01/08 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 185 01/08 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 186 01/08 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 187 01/08 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 188 01/08 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 189 01/08 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 190 01/08 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 191 01/08 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 192 01/08 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 193 01/09 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 194 01/09 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 195 01/09 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 196 01/09 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 197 01/09 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 198 01/09 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 199 01/09 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 200 01/09 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 201 01/09 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 202 01/09 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 203 01/09 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 204 01/09 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 205 01/09 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 206 01/09 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 207 01/09 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 208 01/09 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 209 01/09 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 210 01/09 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 211 01/09 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 212 01/09 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 213 01/09 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 214 01/09 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 215 01/09 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 216 01/09 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 217 01/10 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 218 01/10 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 219 01/10 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 220 01/10 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 221 01/10 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 222 01/10 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 223 01/10 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 224 01/10 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 225 01/10 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 226 01/10 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 227 01/10 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 228 01/10 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 229 01/10 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 230 01/10 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 231 01/10 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 232 01/10 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 233 01/10 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 234 01/10 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 235 01/10 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 236 01/10 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 237 01/10 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 238 01/10 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 239 01/10 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 240 01/10 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 241 01/11 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 242 01/11 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 243 01/11 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 244 01/11 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 245 01/11 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 246 01/11 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 247 01/11 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 248 01/11 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 249 01/11 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 250 01/11 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 251 01/11 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 252 01/11 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 253 01/11 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 254 01/11 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 255 01/11 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 256 01/11 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 257 01/11 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 258 01/11 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 259 01/11 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 260 01/11 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 261 01/11 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 262 01/11 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 263 01/11 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 264 01/11 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 265 01/12 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 266 01/12 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 267 01/12 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 268 01/12 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 269 01/12 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 270 01/12 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 271 01/12 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 272 01/12 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 273 01/12 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 274 01/12 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 275 01/12 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 276 01/12 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 277 01/12 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 278 01/12 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 279 01/12 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 280 01/12 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 281 01/12 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 282 01/12 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 283 01/12 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 284 01/12 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 285 01/12 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 286 01/12 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 287 01/12 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 288 01/12 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 289 01/13 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 290 01/13 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 291 01/13 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 292 01/13 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 293 01/13 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 294 01/13 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 295 01/13 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 296 01/13 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 297 01/13 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 298 01/13 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 299 01/13 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 300 01/13 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 301 01/13 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 302 01/13 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 303 01/13 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 304 01/13 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 305 01/13 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 306 01/13 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 307 01/13 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 308 01/13 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 309 01/13 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 310 01/13 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 311 01/13 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 312 01/13 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 313 01/14 00:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 314 01/14 01:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 315 01/14 02:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 316 01/14 03:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 317 01/14 04:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 318 01/14 05:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 319 01/14 06:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 320 01/14 07:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 321 01/14 08:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 322 01/14 09:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 323 01/14 10:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 324 01/14 11:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 325 01/14 12:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 326 01/14 13:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 327 01/14 14:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 328 01/14 15:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 329 01/14 16:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 330 01/14 17:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 331 01/14 18:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 332 01/14 19:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 333 01/14 20:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 334 01/14 21:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 335 01/14 22:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +fr - it 1 336 01/14 23:00 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 diff --git a/tests/integration/raw_studies_blueprint/assets/aggregate_links_raw_data/test-03.result.tsv b/tests/integration/raw_studies_blueprint/assets/aggregate_links_raw_data/test-03.result.tsv new file mode 100644 index 0000000000..00b95e8ac9 --- /dev/null +++ b/tests/integration/raw_studies_blueprint/assets/aggregate_links_raw_data/test-03.result.tsv @@ -0,0 +1,2017 @@ +link mcYear timeId time UCAP LIN. FLOW QUAD. +de - fr 1 1 01/01 00:00 0.0 0.0 +de - fr 1 2 01/01 01:00 0.0 0.0 +de - fr 1 3 01/01 02:00 0.0 0.0 +de - fr 1 4 01/01 03:00 0.0 0.0 +de - fr 1 5 01/01 04:00 0.0 0.0 +de - fr 1 6 01/01 05:00 0.0 0.0 +de - fr 1 7 01/01 06:00 0.0 0.0 +de - fr 1 8 01/01 07:00 0.0 0.0 +de - fr 1 9 01/01 08:00 0.0 0.0 +de - fr 1 10 01/01 09:00 0.0 0.0 +de - fr 1 11 01/01 10:00 0.0 0.0 +de - fr 1 12 01/01 11:00 0.0 0.0 +de - fr 1 13 01/01 12:00 0.0 0.0 +de - fr 1 14 01/01 13:00 0.0 0.0 +de - fr 1 15 01/01 14:00 0.0 0.0 +de - fr 1 16 01/01 15:00 0.0 0.0 +de - fr 1 17 01/01 16:00 0.0 0.0 +de - fr 1 18 01/01 17:00 0.0 0.0 +de - fr 1 19 01/01 18:00 0.0 0.0 +de - fr 1 20 01/01 19:00 0.0 0.0 +de - fr 1 21 01/01 20:00 0.0 0.0 +de - fr 1 22 01/01 21:00 0.0 0.0 +de - fr 1 23 01/01 22:00 0.0 0.0 +de - fr 1 24 01/01 23:00 0.0 0.0 +de - fr 1 25 01/02 00:00 0.0 0.0 +de - fr 1 26 01/02 01:00 0.0 0.0 +de - fr 1 27 01/02 02:00 0.0 0.0 +de - fr 1 28 01/02 03:00 0.0 0.0 +de - fr 1 29 01/02 04:00 0.0 0.0 +de - fr 1 30 01/02 05:00 0.0 0.0 +de - fr 1 31 01/02 06:00 0.0 0.0 +de - fr 1 32 01/02 07:00 0.0 0.0 +de - fr 1 33 01/02 08:00 0.0 0.0 +de - fr 1 34 01/02 09:00 0.0 0.0 +de - fr 1 35 01/02 10:00 0.0 0.0 +de - fr 1 36 01/02 11:00 0.0 0.0 +de - fr 1 37 01/02 12:00 0.0 0.0 +de - fr 1 38 01/02 13:00 0.0 0.0 +de - fr 1 39 01/02 14:00 0.0 0.0 +de - fr 1 40 01/02 15:00 0.0 0.0 +de - fr 1 41 01/02 16:00 0.0 0.0 +de - fr 1 42 01/02 17:00 0.0 0.0 +de - fr 1 43 01/02 18:00 0.0 0.0 +de - fr 1 44 01/02 19:00 0.0 0.0 +de - fr 1 45 01/02 20:00 0.0 0.0 +de - fr 1 46 01/02 21:00 0.0 0.0 +de - fr 1 47 01/02 22:00 0.0 0.0 +de - fr 1 48 01/02 23:00 0.0 0.0 +de - fr 1 49 01/03 00:00 0.0 0.0 +de - fr 1 50 01/03 01:00 0.0 0.0 +de - fr 1 51 01/03 02:00 0.0 0.0 +de - fr 1 52 01/03 03:00 0.0 0.0 +de - fr 1 53 01/03 04:00 0.0 0.0 +de - fr 1 54 01/03 05:00 0.0 0.0 +de - fr 1 55 01/03 06:00 0.0 0.0 +de - fr 1 56 01/03 07:00 0.0 0.0 +de - fr 1 57 01/03 08:00 0.0 0.0 +de - fr 1 58 01/03 09:00 0.0 0.0 +de - fr 1 59 01/03 10:00 0.0 0.0 +de - fr 1 60 01/03 11:00 0.0 0.0 +de - fr 1 61 01/03 12:00 0.0 0.0 +de - fr 1 62 01/03 13:00 0.0 0.0 +de - fr 1 63 01/03 14:00 0.0 0.0 +de - fr 1 64 01/03 15:00 0.0 0.0 +de - fr 1 65 01/03 16:00 0.0 0.0 +de - fr 1 66 01/03 17:00 0.0 0.0 +de - fr 1 67 01/03 18:00 0.0 0.0 +de - fr 1 68 01/03 19:00 0.0 0.0 +de - fr 1 69 01/03 20:00 0.0 0.0 +de - fr 1 70 01/03 21:00 0.0 0.0 +de - fr 1 71 01/03 22:00 0.0 0.0 +de - fr 1 72 01/03 23:00 0.0 0.0 +de - fr 1 73 01/04 00:00 0.0 0.0 +de - fr 1 74 01/04 01:00 0.0 0.0 +de - fr 1 75 01/04 02:00 0.0 0.0 +de - fr 1 76 01/04 03:00 0.0 0.0 +de - fr 1 77 01/04 04:00 0.0 0.0 +de - fr 1 78 01/04 05:00 0.0 0.0 +de - fr 1 79 01/04 06:00 0.0 0.0 +de - fr 1 80 01/04 07:00 0.0 0.0 +de - fr 1 81 01/04 08:00 0.0 0.0 +de - fr 1 82 01/04 09:00 0.0 0.0 +de - fr 1 83 01/04 10:00 0.0 0.0 +de - fr 1 84 01/04 11:00 0.0 0.0 +de - fr 1 85 01/04 12:00 0.0 0.0 +de - fr 1 86 01/04 13:00 0.0 0.0 +de - fr 1 87 01/04 14:00 0.0 0.0 +de - fr 1 88 01/04 15:00 0.0 0.0 +de - fr 1 89 01/04 16:00 0.0 0.0 +de - fr 1 90 01/04 17:00 0.0 0.0 +de - fr 1 91 01/04 18:00 0.0 0.0 +de - fr 1 92 01/04 19:00 0.0 0.0 +de - fr 1 93 01/04 20:00 0.0 0.0 +de - fr 1 94 01/04 21:00 0.0 0.0 +de - fr 1 95 01/04 22:00 0.0 0.0 +de - fr 1 96 01/04 23:00 0.0 0.0 +de - fr 1 97 01/05 00:00 0.0 0.0 +de - fr 1 98 01/05 01:00 0.0 0.0 +de - fr 1 99 01/05 02:00 0.0 0.0 +de - fr 1 100 01/05 03:00 0.0 0.0 +de - fr 1 101 01/05 04:00 0.0 0.0 +de - fr 1 102 01/05 05:00 0.0 0.0 +de - fr 1 103 01/05 06:00 0.0 0.0 +de - fr 1 104 01/05 07:00 0.0 0.0 +de - fr 1 105 01/05 08:00 0.0 0.0 +de - fr 1 106 01/05 09:00 0.0 0.0 +de - fr 1 107 01/05 10:00 0.0 0.0 +de - fr 1 108 01/05 11:00 0.0 0.0 +de - fr 1 109 01/05 12:00 0.0 0.0 +de - fr 1 110 01/05 13:00 0.0 0.0 +de - fr 1 111 01/05 14:00 0.0 0.0 +de - fr 1 112 01/05 15:00 0.0 0.0 +de - fr 1 113 01/05 16:00 0.0 0.0 +de - fr 1 114 01/05 17:00 0.0 0.0 +de - fr 1 115 01/05 18:00 0.0 0.0 +de - fr 1 116 01/05 19:00 0.0 0.0 +de - fr 1 117 01/05 20:00 0.0 0.0 +de - fr 1 118 01/05 21:00 0.0 0.0 +de - fr 1 119 01/05 22:00 0.0 0.0 +de - fr 1 120 01/05 23:00 0.0 0.0 +de - fr 1 121 01/06 00:00 0.0 0.0 +de - fr 1 122 01/06 01:00 0.0 0.0 +de - fr 1 123 01/06 02:00 0.0 0.0 +de - fr 1 124 01/06 03:00 0.0 0.0 +de - fr 1 125 01/06 04:00 0.0 0.0 +de - fr 1 126 01/06 05:00 0.0 0.0 +de - fr 1 127 01/06 06:00 0.0 0.0 +de - fr 1 128 01/06 07:00 0.0 0.0 +de - fr 1 129 01/06 08:00 0.0 0.0 +de - fr 1 130 01/06 09:00 0.0 0.0 +de - fr 1 131 01/06 10:00 0.0 0.0 +de - fr 1 132 01/06 11:00 0.0 0.0 +de - fr 1 133 01/06 12:00 0.0 0.0 +de - fr 1 134 01/06 13:00 0.0 0.0 +de - fr 1 135 01/06 14:00 0.0 0.0 +de - fr 1 136 01/06 15:00 0.0 0.0 +de - fr 1 137 01/06 16:00 0.0 0.0 +de - fr 1 138 01/06 17:00 0.0 0.0 +de - fr 1 139 01/06 18:00 0.0 0.0 +de - fr 1 140 01/06 19:00 0.0 0.0 +de - fr 1 141 01/06 20:00 0.0 0.0 +de - fr 1 142 01/06 21:00 0.0 0.0 +de - fr 1 143 01/06 22:00 0.0 0.0 +de - fr 1 144 01/06 23:00 0.0 0.0 +de - fr 1 145 01/07 00:00 0.0 0.0 +de - fr 1 146 01/07 01:00 0.0 0.0 +de - fr 1 147 01/07 02:00 0.0 0.0 +de - fr 1 148 01/07 03:00 0.0 0.0 +de - fr 1 149 01/07 04:00 0.0 0.0 +de - fr 1 150 01/07 05:00 0.0 0.0 +de - fr 1 151 01/07 06:00 0.0 0.0 +de - fr 1 152 01/07 07:00 0.0 0.0 +de - fr 1 153 01/07 08:00 0.0 0.0 +de - fr 1 154 01/07 09:00 0.0 0.0 +de - fr 1 155 01/07 10:00 0.0 0.0 +de - fr 1 156 01/07 11:00 0.0 0.0 +de - fr 1 157 01/07 12:00 0.0 0.0 +de - fr 1 158 01/07 13:00 0.0 0.0 +de - fr 1 159 01/07 14:00 0.0 0.0 +de - fr 1 160 01/07 15:00 0.0 0.0 +de - fr 1 161 01/07 16:00 0.0 0.0 +de - fr 1 162 01/07 17:00 0.0 0.0 +de - fr 1 163 01/07 18:00 0.0 0.0 +de - fr 1 164 01/07 19:00 0.0 0.0 +de - fr 1 165 01/07 20:00 0.0 0.0 +de - fr 1 166 01/07 21:00 0.0 0.0 +de - fr 1 167 01/07 22:00 0.0 0.0 +de - fr 1 168 01/07 23:00 0.0 0.0 +de - fr 1 169 01/08 00:00 0.0 0.0 +de - fr 1 170 01/08 01:00 0.0 0.0 +de - fr 1 171 01/08 02:00 0.0 0.0 +de - fr 1 172 01/08 03:00 0.0 0.0 +de - fr 1 173 01/08 04:00 0.0 0.0 +de - fr 1 174 01/08 05:00 0.0 0.0 +de - fr 1 175 01/08 06:00 0.0 0.0 +de - fr 1 176 01/08 07:00 0.0 0.0 +de - fr 1 177 01/08 08:00 0.0 0.0 +de - fr 1 178 01/08 09:00 0.0 0.0 +de - fr 1 179 01/08 10:00 0.0 0.0 +de - fr 1 180 01/08 11:00 0.0 0.0 +de - fr 1 181 01/08 12:00 0.0 0.0 +de - fr 1 182 01/08 13:00 0.0 0.0 +de - fr 1 183 01/08 14:00 0.0 0.0 +de - fr 1 184 01/08 15:00 0.0 0.0 +de - fr 1 185 01/08 16:00 0.0 0.0 +de - fr 1 186 01/08 17:00 0.0 0.0 +de - fr 1 187 01/08 18:00 0.0 0.0 +de - fr 1 188 01/08 19:00 0.0 0.0 +de - fr 1 189 01/08 20:00 0.0 0.0 +de - fr 1 190 01/08 21:00 0.0 0.0 +de - fr 1 191 01/08 22:00 0.0 0.0 +de - fr 1 192 01/08 23:00 0.0 0.0 +de - fr 1 193 01/09 00:00 0.0 0.0 +de - fr 1 194 01/09 01:00 0.0 0.0 +de - fr 1 195 01/09 02:00 0.0 0.0 +de - fr 1 196 01/09 03:00 0.0 0.0 +de - fr 1 197 01/09 04:00 0.0 0.0 +de - fr 1 198 01/09 05:00 0.0 0.0 +de - fr 1 199 01/09 06:00 0.0 0.0 +de - fr 1 200 01/09 07:00 0.0 0.0 +de - fr 1 201 01/09 08:00 0.0 0.0 +de - fr 1 202 01/09 09:00 0.0 0.0 +de - fr 1 203 01/09 10:00 0.0 0.0 +de - fr 1 204 01/09 11:00 0.0 0.0 +de - fr 1 205 01/09 12:00 0.0 0.0 +de - fr 1 206 01/09 13:00 0.0 0.0 +de - fr 1 207 01/09 14:00 0.0 0.0 +de - fr 1 208 01/09 15:00 0.0 0.0 +de - fr 1 209 01/09 16:00 0.0 0.0 +de - fr 1 210 01/09 17:00 0.0 0.0 +de - fr 1 211 01/09 18:00 0.0 0.0 +de - fr 1 212 01/09 19:00 0.0 0.0 +de - fr 1 213 01/09 20:00 0.0 0.0 +de - fr 1 214 01/09 21:00 0.0 0.0 +de - fr 1 215 01/09 22:00 0.0 0.0 +de - fr 1 216 01/09 23:00 0.0 0.0 +de - fr 1 217 01/10 00:00 0.0 0.0 +de - fr 1 218 01/10 01:00 0.0 0.0 +de - fr 1 219 01/10 02:00 0.0 0.0 +de - fr 1 220 01/10 03:00 0.0 0.0 +de - fr 1 221 01/10 04:00 0.0 0.0 +de - fr 1 222 01/10 05:00 0.0 0.0 +de - fr 1 223 01/10 06:00 0.0 0.0 +de - fr 1 224 01/10 07:00 0.0 0.0 +de - fr 1 225 01/10 08:00 0.0 0.0 +de - fr 1 226 01/10 09:00 0.0 0.0 +de - fr 1 227 01/10 10:00 0.0 0.0 +de - fr 1 228 01/10 11:00 0.0 0.0 +de - fr 1 229 01/10 12:00 0.0 0.0 +de - fr 1 230 01/10 13:00 0.0 0.0 +de - fr 1 231 01/10 14:00 0.0 0.0 +de - fr 1 232 01/10 15:00 0.0 0.0 +de - fr 1 233 01/10 16:00 0.0 0.0 +de - fr 1 234 01/10 17:00 0.0 0.0 +de - fr 1 235 01/10 18:00 0.0 0.0 +de - fr 1 236 01/10 19:00 0.0 0.0 +de - fr 1 237 01/10 20:00 0.0 0.0 +de - fr 1 238 01/10 21:00 0.0 0.0 +de - fr 1 239 01/10 22:00 0.0 0.0 +de - fr 1 240 01/10 23:00 0.0 0.0 +de - fr 1 241 01/11 00:00 0.0 0.0 +de - fr 1 242 01/11 01:00 0.0 0.0 +de - fr 1 243 01/11 02:00 0.0 0.0 +de - fr 1 244 01/11 03:00 0.0 0.0 +de - fr 1 245 01/11 04:00 0.0 0.0 +de - fr 1 246 01/11 05:00 0.0 0.0 +de - fr 1 247 01/11 06:00 0.0 0.0 +de - fr 1 248 01/11 07:00 0.0 0.0 +de - fr 1 249 01/11 08:00 0.0 0.0 +de - fr 1 250 01/11 09:00 0.0 0.0 +de - fr 1 251 01/11 10:00 0.0 0.0 +de - fr 1 252 01/11 11:00 0.0 0.0 +de - fr 1 253 01/11 12:00 0.0 0.0 +de - fr 1 254 01/11 13:00 0.0 0.0 +de - fr 1 255 01/11 14:00 0.0 0.0 +de - fr 1 256 01/11 15:00 0.0 0.0 +de - fr 1 257 01/11 16:00 0.0 0.0 +de - fr 1 258 01/11 17:00 0.0 0.0 +de - fr 1 259 01/11 18:00 0.0 0.0 +de - fr 1 260 01/11 19:00 0.0 0.0 +de - fr 1 261 01/11 20:00 0.0 0.0 +de - fr 1 262 01/11 21:00 0.0 0.0 +de - fr 1 263 01/11 22:00 0.0 0.0 +de - fr 1 264 01/11 23:00 0.0 0.0 +de - fr 1 265 01/12 00:00 0.0 0.0 +de - fr 1 266 01/12 01:00 0.0 0.0 +de - fr 1 267 01/12 02:00 0.0 0.0 +de - fr 1 268 01/12 03:00 0.0 0.0 +de - fr 1 269 01/12 04:00 0.0 0.0 +de - fr 1 270 01/12 05:00 0.0 0.0 +de - fr 1 271 01/12 06:00 0.0 0.0 +de - fr 1 272 01/12 07:00 0.0 0.0 +de - fr 1 273 01/12 08:00 0.0 0.0 +de - fr 1 274 01/12 09:00 0.0 0.0 +de - fr 1 275 01/12 10:00 0.0 0.0 +de - fr 1 276 01/12 11:00 0.0 0.0 +de - fr 1 277 01/12 12:00 0.0 0.0 +de - fr 1 278 01/12 13:00 0.0 0.0 +de - fr 1 279 01/12 14:00 0.0 0.0 +de - fr 1 280 01/12 15:00 0.0 0.0 +de - fr 1 281 01/12 16:00 0.0 0.0 +de - fr 1 282 01/12 17:00 0.0 0.0 +de - fr 1 283 01/12 18:00 0.0 0.0 +de - fr 1 284 01/12 19:00 0.0 0.0 +de - fr 1 285 01/12 20:00 0.0 0.0 +de - fr 1 286 01/12 21:00 0.0 0.0 +de - fr 1 287 01/12 22:00 0.0 0.0 +de - fr 1 288 01/12 23:00 0.0 0.0 +de - fr 1 289 01/13 00:00 0.0 0.0 +de - fr 1 290 01/13 01:00 0.0 0.0 +de - fr 1 291 01/13 02:00 0.0 0.0 +de - fr 1 292 01/13 03:00 0.0 0.0 +de - fr 1 293 01/13 04:00 0.0 0.0 +de - fr 1 294 01/13 05:00 0.0 0.0 +de - fr 1 295 01/13 06:00 0.0 0.0 +de - fr 1 296 01/13 07:00 0.0 0.0 +de - fr 1 297 01/13 08:00 0.0 0.0 +de - fr 1 298 01/13 09:00 0.0 0.0 +de - fr 1 299 01/13 10:00 0.0 0.0 +de - fr 1 300 01/13 11:00 0.0 0.0 +de - fr 1 301 01/13 12:00 0.0 0.0 +de - fr 1 302 01/13 13:00 0.0 0.0 +de - fr 1 303 01/13 14:00 0.0 0.0 +de - fr 1 304 01/13 15:00 0.0 0.0 +de - fr 1 305 01/13 16:00 0.0 0.0 +de - fr 1 306 01/13 17:00 0.0 0.0 +de - fr 1 307 01/13 18:00 0.0 0.0 +de - fr 1 308 01/13 19:00 0.0 0.0 +de - fr 1 309 01/13 20:00 0.0 0.0 +de - fr 1 310 01/13 21:00 0.0 0.0 +de - fr 1 311 01/13 22:00 0.0 0.0 +de - fr 1 312 01/13 23:00 0.0 0.0 +de - fr 1 313 01/14 00:00 0.0 0.0 +de - fr 1 314 01/14 01:00 0.0 0.0 +de - fr 1 315 01/14 02:00 0.0 0.0 +de - fr 1 316 01/14 03:00 0.0 0.0 +de - fr 1 317 01/14 04:00 0.0 0.0 +de - fr 1 318 01/14 05:00 0.0 0.0 +de - fr 1 319 01/14 06:00 0.0 0.0 +de - fr 1 320 01/14 07:00 0.0 0.0 +de - fr 1 321 01/14 08:00 0.0 0.0 +de - fr 1 322 01/14 09:00 0.0 0.0 +de - fr 1 323 01/14 10:00 0.0 0.0 +de - fr 1 324 01/14 11:00 0.0 0.0 +de - fr 1 325 01/14 12:00 0.0 0.0 +de - fr 1 326 01/14 13:00 0.0 0.0 +de - fr 1 327 01/14 14:00 0.0 0.0 +de - fr 1 328 01/14 15:00 0.0 0.0 +de - fr 1 329 01/14 16:00 0.0 0.0 +de - fr 1 330 01/14 17:00 0.0 0.0 +de - fr 1 331 01/14 18:00 0.0 0.0 +de - fr 1 332 01/14 19:00 0.0 0.0 +de - fr 1 333 01/14 20:00 0.0 0.0 +de - fr 1 334 01/14 21:00 0.0 0.0 +de - fr 1 335 01/14 22:00 0.0 0.0 +de - fr 1 336 01/14 23:00 0.0 0.0 +es - fr 1 1 01/01 00:00 0.0 0.0 +es - fr 1 2 01/01 01:00 0.0 0.0 +es - fr 1 3 01/01 02:00 0.0 0.0 +es - fr 1 4 01/01 03:00 0.0 0.0 +es - fr 1 5 01/01 04:00 0.0 0.0 +es - fr 1 6 01/01 05:00 0.0 0.0 +es - fr 1 7 01/01 06:00 0.0 0.0 +es - fr 1 8 01/01 07:00 0.0 0.0 +es - fr 1 9 01/01 08:00 0.0 0.0 +es - fr 1 10 01/01 09:00 0.0 0.0 +es - fr 1 11 01/01 10:00 0.0 0.0 +es - fr 1 12 01/01 11:00 0.0 0.0 +es - fr 1 13 01/01 12:00 0.0 0.0 +es - fr 1 14 01/01 13:00 0.0 0.0 +es - fr 1 15 01/01 14:00 0.0 0.0 +es - fr 1 16 01/01 15:00 0.0 0.0 +es - fr 1 17 01/01 16:00 0.0 0.0 +es - fr 1 18 01/01 17:00 0.0 0.0 +es - fr 1 19 01/01 18:00 0.0 0.0 +es - fr 1 20 01/01 19:00 0.0 0.0 +es - fr 1 21 01/01 20:00 0.0 0.0 +es - fr 1 22 01/01 21:00 0.0 0.0 +es - fr 1 23 01/01 22:00 0.0 0.0 +es - fr 1 24 01/01 23:00 0.0 0.0 +es - fr 1 25 01/02 00:00 0.0 0.0 +es - fr 1 26 01/02 01:00 0.0 0.0 +es - fr 1 27 01/02 02:00 0.0 0.0 +es - fr 1 28 01/02 03:00 0.0 0.0 +es - fr 1 29 01/02 04:00 0.0 0.0 +es - fr 1 30 01/02 05:00 0.0 0.0 +es - fr 1 31 01/02 06:00 0.0 0.0 +es - fr 1 32 01/02 07:00 0.0 0.0 +es - fr 1 33 01/02 08:00 0.0 0.0 +es - fr 1 34 01/02 09:00 0.0 0.0 +es - fr 1 35 01/02 10:00 0.0 0.0 +es - fr 1 36 01/02 11:00 0.0 0.0 +es - fr 1 37 01/02 12:00 0.0 0.0 +es - fr 1 38 01/02 13:00 0.0 0.0 +es - fr 1 39 01/02 14:00 0.0 0.0 +es - fr 1 40 01/02 15:00 0.0 0.0 +es - fr 1 41 01/02 16:00 0.0 0.0 +es - fr 1 42 01/02 17:00 0.0 0.0 +es - fr 1 43 01/02 18:00 0.0 0.0 +es - fr 1 44 01/02 19:00 0.0 0.0 +es - fr 1 45 01/02 20:00 0.0 0.0 +es - fr 1 46 01/02 21:00 0.0 0.0 +es - fr 1 47 01/02 22:00 0.0 0.0 +es - fr 1 48 01/02 23:00 0.0 0.0 +es - fr 1 49 01/03 00:00 0.0 0.0 +es - fr 1 50 01/03 01:00 0.0 0.0 +es - fr 1 51 01/03 02:00 0.0 0.0 +es - fr 1 52 01/03 03:00 0.0 0.0 +es - fr 1 53 01/03 04:00 0.0 0.0 +es - fr 1 54 01/03 05:00 0.0 0.0 +es - fr 1 55 01/03 06:00 0.0 0.0 +es - fr 1 56 01/03 07:00 0.0 0.0 +es - fr 1 57 01/03 08:00 0.0 0.0 +es - fr 1 58 01/03 09:00 0.0 0.0 +es - fr 1 59 01/03 10:00 0.0 0.0 +es - fr 1 60 01/03 11:00 0.0 0.0 +es - fr 1 61 01/03 12:00 0.0 0.0 +es - fr 1 62 01/03 13:00 0.0 0.0 +es - fr 1 63 01/03 14:00 0.0 0.0 +es - fr 1 64 01/03 15:00 0.0 0.0 +es - fr 1 65 01/03 16:00 0.0 0.0 +es - fr 1 66 01/03 17:00 0.0 0.0 +es - fr 1 67 01/03 18:00 0.0 0.0 +es - fr 1 68 01/03 19:00 0.0 0.0 +es - fr 1 69 01/03 20:00 0.0 0.0 +es - fr 1 70 01/03 21:00 0.0 0.0 +es - fr 1 71 01/03 22:00 0.0 0.0 +es - fr 1 72 01/03 23:00 0.0 0.0 +es - fr 1 73 01/04 00:00 0.0 0.0 +es - fr 1 74 01/04 01:00 0.0 0.0 +es - fr 1 75 01/04 02:00 0.0 0.0 +es - fr 1 76 01/04 03:00 0.0 0.0 +es - fr 1 77 01/04 04:00 0.0 0.0 +es - fr 1 78 01/04 05:00 0.0 0.0 +es - fr 1 79 01/04 06:00 0.0 0.0 +es - fr 1 80 01/04 07:00 0.0 0.0 +es - fr 1 81 01/04 08:00 0.0 0.0 +es - fr 1 82 01/04 09:00 0.0 0.0 +es - fr 1 83 01/04 10:00 0.0 0.0 +es - fr 1 84 01/04 11:00 0.0 0.0 +es - fr 1 85 01/04 12:00 0.0 0.0 +es - fr 1 86 01/04 13:00 0.0 0.0 +es - fr 1 87 01/04 14:00 0.0 0.0 +es - fr 1 88 01/04 15:00 0.0 0.0 +es - fr 1 89 01/04 16:00 0.0 0.0 +es - fr 1 90 01/04 17:00 0.0 0.0 +es - fr 1 91 01/04 18:00 0.0 0.0 +es - fr 1 92 01/04 19:00 0.0 0.0 +es - fr 1 93 01/04 20:00 0.0 0.0 +es - fr 1 94 01/04 21:00 0.0 0.0 +es - fr 1 95 01/04 22:00 0.0 0.0 +es - fr 1 96 01/04 23:00 0.0 0.0 +es - fr 1 97 01/05 00:00 0.0 0.0 +es - fr 1 98 01/05 01:00 0.0 0.0 +es - fr 1 99 01/05 02:00 0.0 0.0 +es - fr 1 100 01/05 03:00 0.0 0.0 +es - fr 1 101 01/05 04:00 0.0 0.0 +es - fr 1 102 01/05 05:00 0.0 0.0 +es - fr 1 103 01/05 06:00 0.0 0.0 +es - fr 1 104 01/05 07:00 0.0 0.0 +es - fr 1 105 01/05 08:00 0.0 0.0 +es - fr 1 106 01/05 09:00 0.0 0.0 +es - fr 1 107 01/05 10:00 0.0 0.0 +es - fr 1 108 01/05 11:00 0.0 0.0 +es - fr 1 109 01/05 12:00 0.0 0.0 +es - fr 1 110 01/05 13:00 0.0 0.0 +es - fr 1 111 01/05 14:00 0.0 0.0 +es - fr 1 112 01/05 15:00 0.0 0.0 +es - fr 1 113 01/05 16:00 0.0 0.0 +es - fr 1 114 01/05 17:00 0.0 0.0 +es - fr 1 115 01/05 18:00 0.0 0.0 +es - fr 1 116 01/05 19:00 0.0 0.0 +es - fr 1 117 01/05 20:00 0.0 0.0 +es - fr 1 118 01/05 21:00 0.0 0.0 +es - fr 1 119 01/05 22:00 0.0 0.0 +es - fr 1 120 01/05 23:00 0.0 0.0 +es - fr 1 121 01/06 00:00 0.0 0.0 +es - fr 1 122 01/06 01:00 0.0 0.0 +es - fr 1 123 01/06 02:00 0.0 0.0 +es - fr 1 124 01/06 03:00 0.0 0.0 +es - fr 1 125 01/06 04:00 0.0 0.0 +es - fr 1 126 01/06 05:00 0.0 0.0 +es - fr 1 127 01/06 06:00 0.0 0.0 +es - fr 1 128 01/06 07:00 0.0 0.0 +es - fr 1 129 01/06 08:00 0.0 0.0 +es - fr 1 130 01/06 09:00 0.0 0.0 +es - fr 1 131 01/06 10:00 0.0 0.0 +es - fr 1 132 01/06 11:00 0.0 0.0 +es - fr 1 133 01/06 12:00 0.0 0.0 +es - fr 1 134 01/06 13:00 0.0 0.0 +es - fr 1 135 01/06 14:00 0.0 0.0 +es - fr 1 136 01/06 15:00 0.0 0.0 +es - fr 1 137 01/06 16:00 0.0 0.0 +es - fr 1 138 01/06 17:00 0.0 0.0 +es - fr 1 139 01/06 18:00 0.0 0.0 +es - fr 1 140 01/06 19:00 0.0 0.0 +es - fr 1 141 01/06 20:00 0.0 0.0 +es - fr 1 142 01/06 21:00 0.0 0.0 +es - fr 1 143 01/06 22:00 0.0 0.0 +es - fr 1 144 01/06 23:00 0.0 0.0 +es - fr 1 145 01/07 00:00 0.0 0.0 +es - fr 1 146 01/07 01:00 0.0 0.0 +es - fr 1 147 01/07 02:00 0.0 0.0 +es - fr 1 148 01/07 03:00 0.0 0.0 +es - fr 1 149 01/07 04:00 0.0 0.0 +es - fr 1 150 01/07 05:00 0.0 0.0 +es - fr 1 151 01/07 06:00 0.0 0.0 +es - fr 1 152 01/07 07:00 0.0 0.0 +es - fr 1 153 01/07 08:00 0.0 0.0 +es - fr 1 154 01/07 09:00 0.0 0.0 +es - fr 1 155 01/07 10:00 0.0 0.0 +es - fr 1 156 01/07 11:00 0.0 0.0 +es - fr 1 157 01/07 12:00 0.0 0.0 +es - fr 1 158 01/07 13:00 0.0 0.0 +es - fr 1 159 01/07 14:00 0.0 0.0 +es - fr 1 160 01/07 15:00 0.0 0.0 +es - fr 1 161 01/07 16:00 0.0 0.0 +es - fr 1 162 01/07 17:00 0.0 0.0 +es - fr 1 163 01/07 18:00 0.0 0.0 +es - fr 1 164 01/07 19:00 0.0 0.0 +es - fr 1 165 01/07 20:00 0.0 0.0 +es - fr 1 166 01/07 21:00 0.0 0.0 +es - fr 1 167 01/07 22:00 0.0 0.0 +es - fr 1 168 01/07 23:00 0.0 0.0 +es - fr 1 169 01/08 00:00 0.0 0.0 +es - fr 1 170 01/08 01:00 0.0 0.0 +es - fr 1 171 01/08 02:00 0.0 0.0 +es - fr 1 172 01/08 03:00 0.0 0.0 +es - fr 1 173 01/08 04:00 0.0 0.0 +es - fr 1 174 01/08 05:00 0.0 0.0 +es - fr 1 175 01/08 06:00 0.0 0.0 +es - fr 1 176 01/08 07:00 0.0 0.0 +es - fr 1 177 01/08 08:00 0.0 0.0 +es - fr 1 178 01/08 09:00 0.0 0.0 +es - fr 1 179 01/08 10:00 0.0 0.0 +es - fr 1 180 01/08 11:00 0.0 0.0 +es - fr 1 181 01/08 12:00 0.0 0.0 +es - fr 1 182 01/08 13:00 0.0 0.0 +es - fr 1 183 01/08 14:00 0.0 0.0 +es - fr 1 184 01/08 15:00 0.0 0.0 +es - fr 1 185 01/08 16:00 0.0 0.0 +es - fr 1 186 01/08 17:00 0.0 0.0 +es - fr 1 187 01/08 18:00 0.0 0.0 +es - fr 1 188 01/08 19:00 0.0 0.0 +es - fr 1 189 01/08 20:00 0.0 0.0 +es - fr 1 190 01/08 21:00 0.0 0.0 +es - fr 1 191 01/08 22:00 0.0 0.0 +es - fr 1 192 01/08 23:00 0.0 0.0 +es - fr 1 193 01/09 00:00 0.0 0.0 +es - fr 1 194 01/09 01:00 0.0 0.0 +es - fr 1 195 01/09 02:00 0.0 0.0 +es - fr 1 196 01/09 03:00 0.0 0.0 +es - fr 1 197 01/09 04:00 0.0 0.0 +es - fr 1 198 01/09 05:00 0.0 0.0 +es - fr 1 199 01/09 06:00 0.0 0.0 +es - fr 1 200 01/09 07:00 0.0 0.0 +es - fr 1 201 01/09 08:00 0.0 0.0 +es - fr 1 202 01/09 09:00 0.0 0.0 +es - fr 1 203 01/09 10:00 0.0 0.0 +es - fr 1 204 01/09 11:00 0.0 0.0 +es - fr 1 205 01/09 12:00 0.0 0.0 +es - fr 1 206 01/09 13:00 0.0 0.0 +es - fr 1 207 01/09 14:00 0.0 0.0 +es - fr 1 208 01/09 15:00 0.0 0.0 +es - fr 1 209 01/09 16:00 0.0 0.0 +es - fr 1 210 01/09 17:00 0.0 0.0 +es - fr 1 211 01/09 18:00 0.0 0.0 +es - fr 1 212 01/09 19:00 0.0 0.0 +es - fr 1 213 01/09 20:00 0.0 0.0 +es - fr 1 214 01/09 21:00 0.0 0.0 +es - fr 1 215 01/09 22:00 0.0 0.0 +es - fr 1 216 01/09 23:00 0.0 0.0 +es - fr 1 217 01/10 00:00 0.0 0.0 +es - fr 1 218 01/10 01:00 0.0 0.0 +es - fr 1 219 01/10 02:00 0.0 0.0 +es - fr 1 220 01/10 03:00 0.0 0.0 +es - fr 1 221 01/10 04:00 0.0 0.0 +es - fr 1 222 01/10 05:00 0.0 0.0 +es - fr 1 223 01/10 06:00 0.0 0.0 +es - fr 1 224 01/10 07:00 0.0 0.0 +es - fr 1 225 01/10 08:00 0.0 0.0 +es - fr 1 226 01/10 09:00 0.0 0.0 +es - fr 1 227 01/10 10:00 0.0 0.0 +es - fr 1 228 01/10 11:00 0.0 0.0 +es - fr 1 229 01/10 12:00 0.0 0.0 +es - fr 1 230 01/10 13:00 0.0 0.0 +es - fr 1 231 01/10 14:00 0.0 0.0 +es - fr 1 232 01/10 15:00 0.0 0.0 +es - fr 1 233 01/10 16:00 0.0 0.0 +es - fr 1 234 01/10 17:00 0.0 0.0 +es - fr 1 235 01/10 18:00 0.0 0.0 +es - fr 1 236 01/10 19:00 0.0 0.0 +es - fr 1 237 01/10 20:00 0.0 0.0 +es - fr 1 238 01/10 21:00 0.0 0.0 +es - fr 1 239 01/10 22:00 0.0 0.0 +es - fr 1 240 01/10 23:00 0.0 0.0 +es - fr 1 241 01/11 00:00 0.0 0.0 +es - fr 1 242 01/11 01:00 0.0 0.0 +es - fr 1 243 01/11 02:00 0.0 0.0 +es - fr 1 244 01/11 03:00 0.0 0.0 +es - fr 1 245 01/11 04:00 0.0 0.0 +es - fr 1 246 01/11 05:00 0.0 0.0 +es - fr 1 247 01/11 06:00 0.0 0.0 +es - fr 1 248 01/11 07:00 0.0 0.0 +es - fr 1 249 01/11 08:00 0.0 0.0 +es - fr 1 250 01/11 09:00 0.0 0.0 +es - fr 1 251 01/11 10:00 0.0 0.0 +es - fr 1 252 01/11 11:00 0.0 0.0 +es - fr 1 253 01/11 12:00 0.0 0.0 +es - fr 1 254 01/11 13:00 0.0 0.0 +es - fr 1 255 01/11 14:00 0.0 0.0 +es - fr 1 256 01/11 15:00 0.0 0.0 +es - fr 1 257 01/11 16:00 0.0 0.0 +es - fr 1 258 01/11 17:00 0.0 0.0 +es - fr 1 259 01/11 18:00 0.0 0.0 +es - fr 1 260 01/11 19:00 0.0 0.0 +es - fr 1 261 01/11 20:00 0.0 0.0 +es - fr 1 262 01/11 21:00 0.0 0.0 +es - fr 1 263 01/11 22:00 0.0 0.0 +es - fr 1 264 01/11 23:00 0.0 0.0 +es - fr 1 265 01/12 00:00 0.0 0.0 +es - fr 1 266 01/12 01:00 0.0 0.0 +es - fr 1 267 01/12 02:00 0.0 0.0 +es - fr 1 268 01/12 03:00 0.0 0.0 +es - fr 1 269 01/12 04:00 0.0 0.0 +es - fr 1 270 01/12 05:00 0.0 0.0 +es - fr 1 271 01/12 06:00 0.0 0.0 +es - fr 1 272 01/12 07:00 0.0 0.0 +es - fr 1 273 01/12 08:00 0.0 0.0 +es - fr 1 274 01/12 09:00 0.0 0.0 +es - fr 1 275 01/12 10:00 0.0 0.0 +es - fr 1 276 01/12 11:00 0.0 0.0 +es - fr 1 277 01/12 12:00 0.0 0.0 +es - fr 1 278 01/12 13:00 0.0 0.0 +es - fr 1 279 01/12 14:00 0.0 0.0 +es - fr 1 280 01/12 15:00 0.0 0.0 +es - fr 1 281 01/12 16:00 0.0 0.0 +es - fr 1 282 01/12 17:00 0.0 0.0 +es - fr 1 283 01/12 18:00 0.0 0.0 +es - fr 1 284 01/12 19:00 0.0 0.0 +es - fr 1 285 01/12 20:00 0.0 0.0 +es - fr 1 286 01/12 21:00 0.0 0.0 +es - fr 1 287 01/12 22:00 0.0 0.0 +es - fr 1 288 01/12 23:00 0.0 0.0 +es - fr 1 289 01/13 00:00 0.0 0.0 +es - fr 1 290 01/13 01:00 0.0 0.0 +es - fr 1 291 01/13 02:00 0.0 0.0 +es - fr 1 292 01/13 03:00 0.0 0.0 +es - fr 1 293 01/13 04:00 0.0 0.0 +es - fr 1 294 01/13 05:00 0.0 0.0 +es - fr 1 295 01/13 06:00 0.0 0.0 +es - fr 1 296 01/13 07:00 0.0 0.0 +es - fr 1 297 01/13 08:00 0.0 0.0 +es - fr 1 298 01/13 09:00 0.0 0.0 +es - fr 1 299 01/13 10:00 0.0 0.0 +es - fr 1 300 01/13 11:00 0.0 0.0 +es - fr 1 301 01/13 12:00 0.0 0.0 +es - fr 1 302 01/13 13:00 0.0 0.0 +es - fr 1 303 01/13 14:00 0.0 0.0 +es - fr 1 304 01/13 15:00 0.0 0.0 +es - fr 1 305 01/13 16:00 0.0 0.0 +es - fr 1 306 01/13 17:00 0.0 0.0 +es - fr 1 307 01/13 18:00 0.0 0.0 +es - fr 1 308 01/13 19:00 0.0 0.0 +es - fr 1 309 01/13 20:00 0.0 0.0 +es - fr 1 310 01/13 21:00 0.0 0.0 +es - fr 1 311 01/13 22:00 0.0 0.0 +es - fr 1 312 01/13 23:00 0.0 0.0 +es - fr 1 313 01/14 00:00 0.0 0.0 +es - fr 1 314 01/14 01:00 0.0 0.0 +es - fr 1 315 01/14 02:00 0.0 0.0 +es - fr 1 316 01/14 03:00 0.0 0.0 +es - fr 1 317 01/14 04:00 0.0 0.0 +es - fr 1 318 01/14 05:00 0.0 0.0 +es - fr 1 319 01/14 06:00 0.0 0.0 +es - fr 1 320 01/14 07:00 0.0 0.0 +es - fr 1 321 01/14 08:00 0.0 0.0 +es - fr 1 322 01/14 09:00 0.0 0.0 +es - fr 1 323 01/14 10:00 0.0 0.0 +es - fr 1 324 01/14 11:00 0.0 0.0 +es - fr 1 325 01/14 12:00 0.0 0.0 +es - fr 1 326 01/14 13:00 0.0 0.0 +es - fr 1 327 01/14 14:00 0.0 0.0 +es - fr 1 328 01/14 15:00 0.0 0.0 +es - fr 1 329 01/14 16:00 0.0 0.0 +es - fr 1 330 01/14 17:00 0.0 0.0 +es - fr 1 331 01/14 18:00 0.0 0.0 +es - fr 1 332 01/14 19:00 0.0 0.0 +es - fr 1 333 01/14 20:00 0.0 0.0 +es - fr 1 334 01/14 21:00 0.0 0.0 +es - fr 1 335 01/14 22:00 0.0 0.0 +es - fr 1 336 01/14 23:00 0.0 0.0 +fr - it 1 1 01/01 00:00 0.0 0.0 +fr - it 1 2 01/01 01:00 0.0 0.0 +fr - it 1 3 01/01 02:00 0.0 0.0 +fr - it 1 4 01/01 03:00 0.0 0.0 +fr - it 1 5 01/01 04:00 0.0 0.0 +fr - it 1 6 01/01 05:00 0.0 0.0 +fr - it 1 7 01/01 06:00 0.0 0.0 +fr - it 1 8 01/01 07:00 0.0 0.0 +fr - it 1 9 01/01 08:00 0.0 0.0 +fr - it 1 10 01/01 09:00 0.0 0.0 +fr - it 1 11 01/01 10:00 0.0 0.0 +fr - it 1 12 01/01 11:00 0.0 0.0 +fr - it 1 13 01/01 12:00 0.0 0.0 +fr - it 1 14 01/01 13:00 0.0 0.0 +fr - it 1 15 01/01 14:00 0.0 0.0 +fr - it 1 16 01/01 15:00 0.0 0.0 +fr - it 1 17 01/01 16:00 0.0 0.0 +fr - it 1 18 01/01 17:00 0.0 0.0 +fr - it 1 19 01/01 18:00 0.0 0.0 +fr - it 1 20 01/01 19:00 0.0 0.0 +fr - it 1 21 01/01 20:00 0.0 0.0 +fr - it 1 22 01/01 21:00 0.0 0.0 +fr - it 1 23 01/01 22:00 0.0 0.0 +fr - it 1 24 01/01 23:00 0.0 0.0 +fr - it 1 25 01/02 00:00 0.0 0.0 +fr - it 1 26 01/02 01:00 0.0 0.0 +fr - it 1 27 01/02 02:00 0.0 0.0 +fr - it 1 28 01/02 03:00 0.0 0.0 +fr - it 1 29 01/02 04:00 0.0 0.0 +fr - it 1 30 01/02 05:00 0.0 0.0 +fr - it 1 31 01/02 06:00 0.0 0.0 +fr - it 1 32 01/02 07:00 0.0 0.0 +fr - it 1 33 01/02 08:00 0.0 0.0 +fr - it 1 34 01/02 09:00 0.0 0.0 +fr - it 1 35 01/02 10:00 0.0 0.0 +fr - it 1 36 01/02 11:00 0.0 0.0 +fr - it 1 37 01/02 12:00 0.0 0.0 +fr - it 1 38 01/02 13:00 0.0 0.0 +fr - it 1 39 01/02 14:00 0.0 0.0 +fr - it 1 40 01/02 15:00 0.0 0.0 +fr - it 1 41 01/02 16:00 0.0 0.0 +fr - it 1 42 01/02 17:00 0.0 0.0 +fr - it 1 43 01/02 18:00 0.0 0.0 +fr - it 1 44 01/02 19:00 0.0 0.0 +fr - it 1 45 01/02 20:00 0.0 0.0 +fr - it 1 46 01/02 21:00 0.0 0.0 +fr - it 1 47 01/02 22:00 0.0 0.0 +fr - it 1 48 01/02 23:00 0.0 0.0 +fr - it 1 49 01/03 00:00 0.0 0.0 +fr - it 1 50 01/03 01:00 0.0 0.0 +fr - it 1 51 01/03 02:00 0.0 0.0 +fr - it 1 52 01/03 03:00 0.0 0.0 +fr - it 1 53 01/03 04:00 0.0 0.0 +fr - it 1 54 01/03 05:00 0.0 0.0 +fr - it 1 55 01/03 06:00 0.0 0.0 +fr - it 1 56 01/03 07:00 0.0 0.0 +fr - it 1 57 01/03 08:00 0.0 0.0 +fr - it 1 58 01/03 09:00 0.0 0.0 +fr - it 1 59 01/03 10:00 0.0 0.0 +fr - it 1 60 01/03 11:00 0.0 0.0 +fr - it 1 61 01/03 12:00 0.0 0.0 +fr - it 1 62 01/03 13:00 0.0 0.0 +fr - it 1 63 01/03 14:00 0.0 0.0 +fr - it 1 64 01/03 15:00 0.0 0.0 +fr - it 1 65 01/03 16:00 0.0 0.0 +fr - it 1 66 01/03 17:00 0.0 0.0 +fr - it 1 67 01/03 18:00 0.0 0.0 +fr - it 1 68 01/03 19:00 0.0 0.0 +fr - it 1 69 01/03 20:00 0.0 0.0 +fr - it 1 70 01/03 21:00 0.0 0.0 +fr - it 1 71 01/03 22:00 0.0 0.0 +fr - it 1 72 01/03 23:00 0.0 0.0 +fr - it 1 73 01/04 00:00 0.0 0.0 +fr - it 1 74 01/04 01:00 0.0 0.0 +fr - it 1 75 01/04 02:00 0.0 0.0 +fr - it 1 76 01/04 03:00 0.0 0.0 +fr - it 1 77 01/04 04:00 0.0 0.0 +fr - it 1 78 01/04 05:00 0.0 0.0 +fr - it 1 79 01/04 06:00 0.0 0.0 +fr - it 1 80 01/04 07:00 0.0 0.0 +fr - it 1 81 01/04 08:00 0.0 0.0 +fr - it 1 82 01/04 09:00 0.0 0.0 +fr - it 1 83 01/04 10:00 0.0 0.0 +fr - it 1 84 01/04 11:00 0.0 0.0 +fr - it 1 85 01/04 12:00 0.0 0.0 +fr - it 1 86 01/04 13:00 0.0 0.0 +fr - it 1 87 01/04 14:00 0.0 0.0 +fr - it 1 88 01/04 15:00 0.0 0.0 +fr - it 1 89 01/04 16:00 0.0 0.0 +fr - it 1 90 01/04 17:00 0.0 0.0 +fr - it 1 91 01/04 18:00 0.0 0.0 +fr - it 1 92 01/04 19:00 0.0 0.0 +fr - it 1 93 01/04 20:00 0.0 0.0 +fr - it 1 94 01/04 21:00 0.0 0.0 +fr - it 1 95 01/04 22:00 0.0 0.0 +fr - it 1 96 01/04 23:00 0.0 0.0 +fr - it 1 97 01/05 00:00 0.0 0.0 +fr - it 1 98 01/05 01:00 0.0 0.0 +fr - it 1 99 01/05 02:00 0.0 0.0 +fr - it 1 100 01/05 03:00 0.0 0.0 +fr - it 1 101 01/05 04:00 0.0 0.0 +fr - it 1 102 01/05 05:00 0.0 0.0 +fr - it 1 103 01/05 06:00 0.0 0.0 +fr - it 1 104 01/05 07:00 0.0 0.0 +fr - it 1 105 01/05 08:00 0.0 0.0 +fr - it 1 106 01/05 09:00 0.0 0.0 +fr - it 1 107 01/05 10:00 0.0 0.0 +fr - it 1 108 01/05 11:00 0.0 0.0 +fr - it 1 109 01/05 12:00 0.0 0.0 +fr - it 1 110 01/05 13:00 0.0 0.0 +fr - it 1 111 01/05 14:00 0.0 0.0 +fr - it 1 112 01/05 15:00 0.0 0.0 +fr - it 1 113 01/05 16:00 0.0 0.0 +fr - it 1 114 01/05 17:00 0.0 0.0 +fr - it 1 115 01/05 18:00 0.0 0.0 +fr - it 1 116 01/05 19:00 0.0 0.0 +fr - it 1 117 01/05 20:00 0.0 0.0 +fr - it 1 118 01/05 21:00 0.0 0.0 +fr - it 1 119 01/05 22:00 0.0 0.0 +fr - it 1 120 01/05 23:00 0.0 0.0 +fr - it 1 121 01/06 00:00 0.0 0.0 +fr - it 1 122 01/06 01:00 0.0 0.0 +fr - it 1 123 01/06 02:00 0.0 0.0 +fr - it 1 124 01/06 03:00 0.0 0.0 +fr - it 1 125 01/06 04:00 0.0 0.0 +fr - it 1 126 01/06 05:00 0.0 0.0 +fr - it 1 127 01/06 06:00 0.0 0.0 +fr - it 1 128 01/06 07:00 0.0 0.0 +fr - it 1 129 01/06 08:00 0.0 0.0 +fr - it 1 130 01/06 09:00 0.0 0.0 +fr - it 1 131 01/06 10:00 0.0 0.0 +fr - it 1 132 01/06 11:00 0.0 0.0 +fr - it 1 133 01/06 12:00 0.0 0.0 +fr - it 1 134 01/06 13:00 0.0 0.0 +fr - it 1 135 01/06 14:00 0.0 0.0 +fr - it 1 136 01/06 15:00 0.0 0.0 +fr - it 1 137 01/06 16:00 0.0 0.0 +fr - it 1 138 01/06 17:00 0.0 0.0 +fr - it 1 139 01/06 18:00 0.0 0.0 +fr - it 1 140 01/06 19:00 0.0 0.0 +fr - it 1 141 01/06 20:00 0.0 0.0 +fr - it 1 142 01/06 21:00 0.0 0.0 +fr - it 1 143 01/06 22:00 0.0 0.0 +fr - it 1 144 01/06 23:00 0.0 0.0 +fr - it 1 145 01/07 00:00 0.0 0.0 +fr - it 1 146 01/07 01:00 0.0 0.0 +fr - it 1 147 01/07 02:00 0.0 0.0 +fr - it 1 148 01/07 03:00 0.0 0.0 +fr - it 1 149 01/07 04:00 0.0 0.0 +fr - it 1 150 01/07 05:00 0.0 0.0 +fr - it 1 151 01/07 06:00 0.0 0.0 +fr - it 1 152 01/07 07:00 0.0 0.0 +fr - it 1 153 01/07 08:00 0.0 0.0 +fr - it 1 154 01/07 09:00 0.0 0.0 +fr - it 1 155 01/07 10:00 0.0 0.0 +fr - it 1 156 01/07 11:00 0.0 0.0 +fr - it 1 157 01/07 12:00 0.0 0.0 +fr - it 1 158 01/07 13:00 0.0 0.0 +fr - it 1 159 01/07 14:00 0.0 0.0 +fr - it 1 160 01/07 15:00 0.0 0.0 +fr - it 1 161 01/07 16:00 0.0 0.0 +fr - it 1 162 01/07 17:00 0.0 0.0 +fr - it 1 163 01/07 18:00 0.0 0.0 +fr - it 1 164 01/07 19:00 0.0 0.0 +fr - it 1 165 01/07 20:00 0.0 0.0 +fr - it 1 166 01/07 21:00 0.0 0.0 +fr - it 1 167 01/07 22:00 0.0 0.0 +fr - it 1 168 01/07 23:00 0.0 0.0 +fr - it 1 169 01/08 00:00 0.0 0.0 +fr - it 1 170 01/08 01:00 0.0 0.0 +fr - it 1 171 01/08 02:00 0.0 0.0 +fr - it 1 172 01/08 03:00 0.0 0.0 +fr - it 1 173 01/08 04:00 0.0 0.0 +fr - it 1 174 01/08 05:00 0.0 0.0 +fr - it 1 175 01/08 06:00 0.0 0.0 +fr - it 1 176 01/08 07:00 0.0 0.0 +fr - it 1 177 01/08 08:00 0.0 0.0 +fr - it 1 178 01/08 09:00 0.0 0.0 +fr - it 1 179 01/08 10:00 0.0 0.0 +fr - it 1 180 01/08 11:00 0.0 0.0 +fr - it 1 181 01/08 12:00 0.0 0.0 +fr - it 1 182 01/08 13:00 0.0 0.0 +fr - it 1 183 01/08 14:00 0.0 0.0 +fr - it 1 184 01/08 15:00 0.0 0.0 +fr - it 1 185 01/08 16:00 0.0 0.0 +fr - it 1 186 01/08 17:00 0.0 0.0 +fr - it 1 187 01/08 18:00 0.0 0.0 +fr - it 1 188 01/08 19:00 0.0 0.0 +fr - it 1 189 01/08 20:00 0.0 0.0 +fr - it 1 190 01/08 21:00 0.0 0.0 +fr - it 1 191 01/08 22:00 0.0 0.0 +fr - it 1 192 01/08 23:00 0.0 0.0 +fr - it 1 193 01/09 00:00 0.0 0.0 +fr - it 1 194 01/09 01:00 0.0 0.0 +fr - it 1 195 01/09 02:00 0.0 0.0 +fr - it 1 196 01/09 03:00 0.0 0.0 +fr - it 1 197 01/09 04:00 0.0 0.0 +fr - it 1 198 01/09 05:00 0.0 0.0 +fr - it 1 199 01/09 06:00 0.0 0.0 +fr - it 1 200 01/09 07:00 0.0 0.0 +fr - it 1 201 01/09 08:00 0.0 0.0 +fr - it 1 202 01/09 09:00 0.0 0.0 +fr - it 1 203 01/09 10:00 0.0 0.0 +fr - it 1 204 01/09 11:00 0.0 0.0 +fr - it 1 205 01/09 12:00 0.0 0.0 +fr - it 1 206 01/09 13:00 0.0 0.0 +fr - it 1 207 01/09 14:00 0.0 0.0 +fr - it 1 208 01/09 15:00 0.0 0.0 +fr - it 1 209 01/09 16:00 0.0 0.0 +fr - it 1 210 01/09 17:00 0.0 0.0 +fr - it 1 211 01/09 18:00 0.0 0.0 +fr - it 1 212 01/09 19:00 0.0 0.0 +fr - it 1 213 01/09 20:00 0.0 0.0 +fr - it 1 214 01/09 21:00 0.0 0.0 +fr - it 1 215 01/09 22:00 0.0 0.0 +fr - it 1 216 01/09 23:00 0.0 0.0 +fr - it 1 217 01/10 00:00 0.0 0.0 +fr - it 1 218 01/10 01:00 0.0 0.0 +fr - it 1 219 01/10 02:00 0.0 0.0 +fr - it 1 220 01/10 03:00 0.0 0.0 +fr - it 1 221 01/10 04:00 0.0 0.0 +fr - it 1 222 01/10 05:00 0.0 0.0 +fr - it 1 223 01/10 06:00 0.0 0.0 +fr - it 1 224 01/10 07:00 0.0 0.0 +fr - it 1 225 01/10 08:00 0.0 0.0 +fr - it 1 226 01/10 09:00 0.0 0.0 +fr - it 1 227 01/10 10:00 0.0 0.0 +fr - it 1 228 01/10 11:00 0.0 0.0 +fr - it 1 229 01/10 12:00 0.0 0.0 +fr - it 1 230 01/10 13:00 0.0 0.0 +fr - it 1 231 01/10 14:00 0.0 0.0 +fr - it 1 232 01/10 15:00 0.0 0.0 +fr - it 1 233 01/10 16:00 0.0 0.0 +fr - it 1 234 01/10 17:00 0.0 0.0 +fr - it 1 235 01/10 18:00 0.0 0.0 +fr - it 1 236 01/10 19:00 0.0 0.0 +fr - it 1 237 01/10 20:00 0.0 0.0 +fr - it 1 238 01/10 21:00 0.0 0.0 +fr - it 1 239 01/10 22:00 0.0 0.0 +fr - it 1 240 01/10 23:00 0.0 0.0 +fr - it 1 241 01/11 00:00 0.0 0.0 +fr - it 1 242 01/11 01:00 0.0 0.0 +fr - it 1 243 01/11 02:00 0.0 0.0 +fr - it 1 244 01/11 03:00 0.0 0.0 +fr - it 1 245 01/11 04:00 0.0 0.0 +fr - it 1 246 01/11 05:00 0.0 0.0 +fr - it 1 247 01/11 06:00 0.0 0.0 +fr - it 1 248 01/11 07:00 0.0 0.0 +fr - it 1 249 01/11 08:00 0.0 0.0 +fr - it 1 250 01/11 09:00 0.0 0.0 +fr - it 1 251 01/11 10:00 0.0 0.0 +fr - it 1 252 01/11 11:00 0.0 0.0 +fr - it 1 253 01/11 12:00 0.0 0.0 +fr - it 1 254 01/11 13:00 0.0 0.0 +fr - it 1 255 01/11 14:00 0.0 0.0 +fr - it 1 256 01/11 15:00 0.0 0.0 +fr - it 1 257 01/11 16:00 0.0 0.0 +fr - it 1 258 01/11 17:00 0.0 0.0 +fr - it 1 259 01/11 18:00 0.0 0.0 +fr - it 1 260 01/11 19:00 0.0 0.0 +fr - it 1 261 01/11 20:00 0.0 0.0 +fr - it 1 262 01/11 21:00 0.0 0.0 +fr - it 1 263 01/11 22:00 0.0 0.0 +fr - it 1 264 01/11 23:00 0.0 0.0 +fr - it 1 265 01/12 00:00 0.0 0.0 +fr - it 1 266 01/12 01:00 0.0 0.0 +fr - it 1 267 01/12 02:00 0.0 0.0 +fr - it 1 268 01/12 03:00 0.0 0.0 +fr - it 1 269 01/12 04:00 0.0 0.0 +fr - it 1 270 01/12 05:00 0.0 0.0 +fr - it 1 271 01/12 06:00 0.0 0.0 +fr - it 1 272 01/12 07:00 0.0 0.0 +fr - it 1 273 01/12 08:00 0.0 0.0 +fr - it 1 274 01/12 09:00 0.0 0.0 +fr - it 1 275 01/12 10:00 0.0 0.0 +fr - it 1 276 01/12 11:00 0.0 0.0 +fr - it 1 277 01/12 12:00 0.0 0.0 +fr - it 1 278 01/12 13:00 0.0 0.0 +fr - it 1 279 01/12 14:00 0.0 0.0 +fr - it 1 280 01/12 15:00 0.0 0.0 +fr - it 1 281 01/12 16:00 0.0 0.0 +fr - it 1 282 01/12 17:00 0.0 0.0 +fr - it 1 283 01/12 18:00 0.0 0.0 +fr - it 1 284 01/12 19:00 0.0 0.0 +fr - it 1 285 01/12 20:00 0.0 0.0 +fr - it 1 286 01/12 21:00 0.0 0.0 +fr - it 1 287 01/12 22:00 0.0 0.0 +fr - it 1 288 01/12 23:00 0.0 0.0 +fr - it 1 289 01/13 00:00 0.0 0.0 +fr - it 1 290 01/13 01:00 0.0 0.0 +fr - it 1 291 01/13 02:00 0.0 0.0 +fr - it 1 292 01/13 03:00 0.0 0.0 +fr - it 1 293 01/13 04:00 0.0 0.0 +fr - it 1 294 01/13 05:00 0.0 0.0 +fr - it 1 295 01/13 06:00 0.0 0.0 +fr - it 1 296 01/13 07:00 0.0 0.0 +fr - it 1 297 01/13 08:00 0.0 0.0 +fr - it 1 298 01/13 09:00 0.0 0.0 +fr - it 1 299 01/13 10:00 0.0 0.0 +fr - it 1 300 01/13 11:00 0.0 0.0 +fr - it 1 301 01/13 12:00 0.0 0.0 +fr - it 1 302 01/13 13:00 0.0 0.0 +fr - it 1 303 01/13 14:00 0.0 0.0 +fr - it 1 304 01/13 15:00 0.0 0.0 +fr - it 1 305 01/13 16:00 0.0 0.0 +fr - it 1 306 01/13 17:00 0.0 0.0 +fr - it 1 307 01/13 18:00 0.0 0.0 +fr - it 1 308 01/13 19:00 0.0 0.0 +fr - it 1 309 01/13 20:00 0.0 0.0 +fr - it 1 310 01/13 21:00 0.0 0.0 +fr - it 1 311 01/13 22:00 0.0 0.0 +fr - it 1 312 01/13 23:00 0.0 0.0 +fr - it 1 313 01/14 00:00 0.0 0.0 +fr - it 1 314 01/14 01:00 0.0 0.0 +fr - it 1 315 01/14 02:00 0.0 0.0 +fr - it 1 316 01/14 03:00 0.0 0.0 +fr - it 1 317 01/14 04:00 0.0 0.0 +fr - it 1 318 01/14 05:00 0.0 0.0 +fr - it 1 319 01/14 06:00 0.0 0.0 +fr - it 1 320 01/14 07:00 0.0 0.0 +fr - it 1 321 01/14 08:00 0.0 0.0 +fr - it 1 322 01/14 09:00 0.0 0.0 +fr - it 1 323 01/14 10:00 0.0 0.0 +fr - it 1 324 01/14 11:00 0.0 0.0 +fr - it 1 325 01/14 12:00 0.0 0.0 +fr - it 1 326 01/14 13:00 0.0 0.0 +fr - it 1 327 01/14 14:00 0.0 0.0 +fr - it 1 328 01/14 15:00 0.0 0.0 +fr - it 1 329 01/14 16:00 0.0 0.0 +fr - it 1 330 01/14 17:00 0.0 0.0 +fr - it 1 331 01/14 18:00 0.0 0.0 +fr - it 1 332 01/14 19:00 0.0 0.0 +fr - it 1 333 01/14 20:00 0.0 0.0 +fr - it 1 334 01/14 21:00 0.0 0.0 +fr - it 1 335 01/14 22:00 0.0 0.0 +fr - it 1 336 01/14 23:00 0.0 0.0 +de - fr 2 1 01/01 00:00 0.0 0.0 +de - fr 2 2 01/01 01:00 0.0 0.0 +de - fr 2 3 01/01 02:00 0.0 0.0 +de - fr 2 4 01/01 03:00 0.0 0.0 +de - fr 2 5 01/01 04:00 0.0 0.0 +de - fr 2 6 01/01 05:00 0.0 0.0 +de - fr 2 7 01/01 06:00 0.0 0.0 +de - fr 2 8 01/01 07:00 0.0 0.0 +de - fr 2 9 01/01 08:00 0.0 0.0 +de - fr 2 10 01/01 09:00 0.0 0.0 +de - fr 2 11 01/01 10:00 0.0 0.0 +de - fr 2 12 01/01 11:00 0.0 0.0 +de - fr 2 13 01/01 12:00 0.0 0.0 +de - fr 2 14 01/01 13:00 0.0 0.0 +de - fr 2 15 01/01 14:00 0.0 0.0 +de - fr 2 16 01/01 15:00 0.0 0.0 +de - fr 2 17 01/01 16:00 0.0 0.0 +de - fr 2 18 01/01 17:00 0.0 0.0 +de - fr 2 19 01/01 18:00 0.0 0.0 +de - fr 2 20 01/01 19:00 0.0 0.0 +de - fr 2 21 01/01 20:00 0.0 0.0 +de - fr 2 22 01/01 21:00 0.0 0.0 +de - fr 2 23 01/01 22:00 0.0 0.0 +de - fr 2 24 01/01 23:00 0.0 0.0 +de - fr 2 25 01/02 00:00 0.0 0.0 +de - fr 2 26 01/02 01:00 0.0 0.0 +de - fr 2 27 01/02 02:00 0.0 0.0 +de - fr 2 28 01/02 03:00 0.0 0.0 +de - fr 2 29 01/02 04:00 0.0 0.0 +de - fr 2 30 01/02 05:00 0.0 0.0 +de - fr 2 31 01/02 06:00 0.0 0.0 +de - fr 2 32 01/02 07:00 0.0 0.0 +de - fr 2 33 01/02 08:00 0.0 0.0 +de - fr 2 34 01/02 09:00 0.0 0.0 +de - fr 2 35 01/02 10:00 0.0 0.0 +de - fr 2 36 01/02 11:00 0.0 0.0 +de - fr 2 37 01/02 12:00 0.0 0.0 +de - fr 2 38 01/02 13:00 0.0 0.0 +de - fr 2 39 01/02 14:00 0.0 0.0 +de - fr 2 40 01/02 15:00 0.0 0.0 +de - fr 2 41 01/02 16:00 0.0 0.0 +de - fr 2 42 01/02 17:00 0.0 0.0 +de - fr 2 43 01/02 18:00 0.0 0.0 +de - fr 2 44 01/02 19:00 0.0 0.0 +de - fr 2 45 01/02 20:00 0.0 0.0 +de - fr 2 46 01/02 21:00 0.0 0.0 +de - fr 2 47 01/02 22:00 0.0 0.0 +de - fr 2 48 01/02 23:00 0.0 0.0 +de - fr 2 49 01/03 00:00 0.0 0.0 +de - fr 2 50 01/03 01:00 0.0 0.0 +de - fr 2 51 01/03 02:00 0.0 0.0 +de - fr 2 52 01/03 03:00 0.0 0.0 +de - fr 2 53 01/03 04:00 0.0 0.0 +de - fr 2 54 01/03 05:00 0.0 0.0 +de - fr 2 55 01/03 06:00 0.0 0.0 +de - fr 2 56 01/03 07:00 0.0 0.0 +de - fr 2 57 01/03 08:00 0.0 0.0 +de - fr 2 58 01/03 09:00 0.0 0.0 +de - fr 2 59 01/03 10:00 0.0 0.0 +de - fr 2 60 01/03 11:00 0.0 0.0 +de - fr 2 61 01/03 12:00 0.0 0.0 +de - fr 2 62 01/03 13:00 0.0 0.0 +de - fr 2 63 01/03 14:00 0.0 0.0 +de - fr 2 64 01/03 15:00 0.0 0.0 +de - fr 2 65 01/03 16:00 0.0 0.0 +de - fr 2 66 01/03 17:00 0.0 0.0 +de - fr 2 67 01/03 18:00 0.0 0.0 +de - fr 2 68 01/03 19:00 0.0 0.0 +de - fr 2 69 01/03 20:00 0.0 0.0 +de - fr 2 70 01/03 21:00 0.0 0.0 +de - fr 2 71 01/03 22:00 0.0 0.0 +de - fr 2 72 01/03 23:00 0.0 0.0 +de - fr 2 73 01/04 00:00 0.0 0.0 +de - fr 2 74 01/04 01:00 0.0 0.0 +de - fr 2 75 01/04 02:00 0.0 0.0 +de - fr 2 76 01/04 03:00 0.0 0.0 +de - fr 2 77 01/04 04:00 0.0 0.0 +de - fr 2 78 01/04 05:00 0.0 0.0 +de - fr 2 79 01/04 06:00 0.0 0.0 +de - fr 2 80 01/04 07:00 0.0 0.0 +de - fr 2 81 01/04 08:00 0.0 0.0 +de - fr 2 82 01/04 09:00 0.0 0.0 +de - fr 2 83 01/04 10:00 0.0 0.0 +de - fr 2 84 01/04 11:00 0.0 0.0 +de - fr 2 85 01/04 12:00 0.0 0.0 +de - fr 2 86 01/04 13:00 0.0 0.0 +de - fr 2 87 01/04 14:00 0.0 0.0 +de - fr 2 88 01/04 15:00 0.0 0.0 +de - fr 2 89 01/04 16:00 0.0 0.0 +de - fr 2 90 01/04 17:00 0.0 0.0 +de - fr 2 91 01/04 18:00 0.0 0.0 +de - fr 2 92 01/04 19:00 0.0 0.0 +de - fr 2 93 01/04 20:00 0.0 0.0 +de - fr 2 94 01/04 21:00 0.0 0.0 +de - fr 2 95 01/04 22:00 0.0 0.0 +de - fr 2 96 01/04 23:00 0.0 0.0 +de - fr 2 97 01/05 00:00 0.0 0.0 +de - fr 2 98 01/05 01:00 0.0 0.0 +de - fr 2 99 01/05 02:00 0.0 0.0 +de - fr 2 100 01/05 03:00 0.0 0.0 +de - fr 2 101 01/05 04:00 0.0 0.0 +de - fr 2 102 01/05 05:00 0.0 0.0 +de - fr 2 103 01/05 06:00 0.0 0.0 +de - fr 2 104 01/05 07:00 0.0 0.0 +de - fr 2 105 01/05 08:00 0.0 0.0 +de - fr 2 106 01/05 09:00 0.0 0.0 +de - fr 2 107 01/05 10:00 0.0 0.0 +de - fr 2 108 01/05 11:00 0.0 0.0 +de - fr 2 109 01/05 12:00 0.0 0.0 +de - fr 2 110 01/05 13:00 0.0 0.0 +de - fr 2 111 01/05 14:00 0.0 0.0 +de - fr 2 112 01/05 15:00 0.0 0.0 +de - fr 2 113 01/05 16:00 0.0 0.0 +de - fr 2 114 01/05 17:00 0.0 0.0 +de - fr 2 115 01/05 18:00 0.0 0.0 +de - fr 2 116 01/05 19:00 0.0 0.0 +de - fr 2 117 01/05 20:00 0.0 0.0 +de - fr 2 118 01/05 21:00 0.0 0.0 +de - fr 2 119 01/05 22:00 0.0 0.0 +de - fr 2 120 01/05 23:00 0.0 0.0 +de - fr 2 121 01/06 00:00 0.0 0.0 +de - fr 2 122 01/06 01:00 0.0 0.0 +de - fr 2 123 01/06 02:00 0.0 0.0 +de - fr 2 124 01/06 03:00 0.0 0.0 +de - fr 2 125 01/06 04:00 0.0 0.0 +de - fr 2 126 01/06 05:00 0.0 0.0 +de - fr 2 127 01/06 06:00 0.0 0.0 +de - fr 2 128 01/06 07:00 0.0 0.0 +de - fr 2 129 01/06 08:00 0.0 0.0 +de - fr 2 130 01/06 09:00 0.0 0.0 +de - fr 2 131 01/06 10:00 0.0 0.0 +de - fr 2 132 01/06 11:00 0.0 0.0 +de - fr 2 133 01/06 12:00 0.0 0.0 +de - fr 2 134 01/06 13:00 0.0 0.0 +de - fr 2 135 01/06 14:00 0.0 0.0 +de - fr 2 136 01/06 15:00 0.0 0.0 +de - fr 2 137 01/06 16:00 0.0 0.0 +de - fr 2 138 01/06 17:00 0.0 0.0 +de - fr 2 139 01/06 18:00 0.0 0.0 +de - fr 2 140 01/06 19:00 0.0 0.0 +de - fr 2 141 01/06 20:00 0.0 0.0 +de - fr 2 142 01/06 21:00 0.0 0.0 +de - fr 2 143 01/06 22:00 0.0 0.0 +de - fr 2 144 01/06 23:00 0.0 0.0 +de - fr 2 145 01/07 00:00 0.0 0.0 +de - fr 2 146 01/07 01:00 0.0 0.0 +de - fr 2 147 01/07 02:00 0.0 0.0 +de - fr 2 148 01/07 03:00 0.0 0.0 +de - fr 2 149 01/07 04:00 0.0 0.0 +de - fr 2 150 01/07 05:00 0.0 0.0 +de - fr 2 151 01/07 06:00 0.0 0.0 +de - fr 2 152 01/07 07:00 0.0 0.0 +de - fr 2 153 01/07 08:00 0.0 0.0 +de - fr 2 154 01/07 09:00 0.0 0.0 +de - fr 2 155 01/07 10:00 0.0 0.0 +de - fr 2 156 01/07 11:00 0.0 0.0 +de - fr 2 157 01/07 12:00 0.0 0.0 +de - fr 2 158 01/07 13:00 0.0 0.0 +de - fr 2 159 01/07 14:00 0.0 0.0 +de - fr 2 160 01/07 15:00 0.0 0.0 +de - fr 2 161 01/07 16:00 0.0 0.0 +de - fr 2 162 01/07 17:00 0.0 0.0 +de - fr 2 163 01/07 18:00 0.0 0.0 +de - fr 2 164 01/07 19:00 0.0 0.0 +de - fr 2 165 01/07 20:00 0.0 0.0 +de - fr 2 166 01/07 21:00 0.0 0.0 +de - fr 2 167 01/07 22:00 0.0 0.0 +de - fr 2 168 01/07 23:00 0.0 0.0 +de - fr 2 169 01/08 00:00 0.0 0.0 +de - fr 2 170 01/08 01:00 0.0 0.0 +de - fr 2 171 01/08 02:00 0.0 0.0 +de - fr 2 172 01/08 03:00 0.0 0.0 +de - fr 2 173 01/08 04:00 0.0 0.0 +de - fr 2 174 01/08 05:00 0.0 0.0 +de - fr 2 175 01/08 06:00 0.0 0.0 +de - fr 2 176 01/08 07:00 0.0 0.0 +de - fr 2 177 01/08 08:00 0.0 0.0 +de - fr 2 178 01/08 09:00 0.0 0.0 +de - fr 2 179 01/08 10:00 0.0 0.0 +de - fr 2 180 01/08 11:00 0.0 0.0 +de - fr 2 181 01/08 12:00 0.0 0.0 +de - fr 2 182 01/08 13:00 0.0 0.0 +de - fr 2 183 01/08 14:00 0.0 0.0 +de - fr 2 184 01/08 15:00 0.0 0.0 +de - fr 2 185 01/08 16:00 0.0 0.0 +de - fr 2 186 01/08 17:00 0.0 0.0 +de - fr 2 187 01/08 18:00 0.0 0.0 +de - fr 2 188 01/08 19:00 0.0 0.0 +de - fr 2 189 01/08 20:00 0.0 0.0 +de - fr 2 190 01/08 21:00 0.0 0.0 +de - fr 2 191 01/08 22:00 0.0 0.0 +de - fr 2 192 01/08 23:00 0.0 0.0 +de - fr 2 193 01/09 00:00 0.0 0.0 +de - fr 2 194 01/09 01:00 0.0 0.0 +de - fr 2 195 01/09 02:00 0.0 0.0 +de - fr 2 196 01/09 03:00 0.0 0.0 +de - fr 2 197 01/09 04:00 0.0 0.0 +de - fr 2 198 01/09 05:00 0.0 0.0 +de - fr 2 199 01/09 06:00 0.0 0.0 +de - fr 2 200 01/09 07:00 0.0 0.0 +de - fr 2 201 01/09 08:00 0.0 0.0 +de - fr 2 202 01/09 09:00 0.0 0.0 +de - fr 2 203 01/09 10:00 0.0 0.0 +de - fr 2 204 01/09 11:00 0.0 0.0 +de - fr 2 205 01/09 12:00 0.0 0.0 +de - fr 2 206 01/09 13:00 0.0 0.0 +de - fr 2 207 01/09 14:00 0.0 0.0 +de - fr 2 208 01/09 15:00 0.0 0.0 +de - fr 2 209 01/09 16:00 0.0 0.0 +de - fr 2 210 01/09 17:00 0.0 0.0 +de - fr 2 211 01/09 18:00 0.0 0.0 +de - fr 2 212 01/09 19:00 0.0 0.0 +de - fr 2 213 01/09 20:00 0.0 0.0 +de - fr 2 214 01/09 21:00 0.0 0.0 +de - fr 2 215 01/09 22:00 0.0 0.0 +de - fr 2 216 01/09 23:00 0.0 0.0 +de - fr 2 217 01/10 00:00 0.0 0.0 +de - fr 2 218 01/10 01:00 0.0 0.0 +de - fr 2 219 01/10 02:00 0.0 0.0 +de - fr 2 220 01/10 03:00 0.0 0.0 +de - fr 2 221 01/10 04:00 0.0 0.0 +de - fr 2 222 01/10 05:00 0.0 0.0 +de - fr 2 223 01/10 06:00 0.0 0.0 +de - fr 2 224 01/10 07:00 0.0 0.0 +de - fr 2 225 01/10 08:00 0.0 0.0 +de - fr 2 226 01/10 09:00 0.0 0.0 +de - fr 2 227 01/10 10:00 0.0 0.0 +de - fr 2 228 01/10 11:00 0.0 0.0 +de - fr 2 229 01/10 12:00 0.0 0.0 +de - fr 2 230 01/10 13:00 0.0 0.0 +de - fr 2 231 01/10 14:00 0.0 0.0 +de - fr 2 232 01/10 15:00 0.0 0.0 +de - fr 2 233 01/10 16:00 0.0 0.0 +de - fr 2 234 01/10 17:00 0.0 0.0 +de - fr 2 235 01/10 18:00 0.0 0.0 +de - fr 2 236 01/10 19:00 0.0 0.0 +de - fr 2 237 01/10 20:00 0.0 0.0 +de - fr 2 238 01/10 21:00 0.0 0.0 +de - fr 2 239 01/10 22:00 0.0 0.0 +de - fr 2 240 01/10 23:00 0.0 0.0 +de - fr 2 241 01/11 00:00 0.0 0.0 +de - fr 2 242 01/11 01:00 0.0 0.0 +de - fr 2 243 01/11 02:00 0.0 0.0 +de - fr 2 244 01/11 03:00 0.0 0.0 +de - fr 2 245 01/11 04:00 0.0 0.0 +de - fr 2 246 01/11 05:00 0.0 0.0 +de - fr 2 247 01/11 06:00 0.0 0.0 +de - fr 2 248 01/11 07:00 0.0 0.0 +de - fr 2 249 01/11 08:00 0.0 0.0 +de - fr 2 250 01/11 09:00 0.0 0.0 +de - fr 2 251 01/11 10:00 0.0 0.0 +de - fr 2 252 01/11 11:00 0.0 0.0 +de - fr 2 253 01/11 12:00 0.0 0.0 +de - fr 2 254 01/11 13:00 0.0 0.0 +de - fr 2 255 01/11 14:00 0.0 0.0 +de - fr 2 256 01/11 15:00 0.0 0.0 +de - fr 2 257 01/11 16:00 0.0 0.0 +de - fr 2 258 01/11 17:00 0.0 0.0 +de - fr 2 259 01/11 18:00 0.0 0.0 +de - fr 2 260 01/11 19:00 0.0 0.0 +de - fr 2 261 01/11 20:00 0.0 0.0 +de - fr 2 262 01/11 21:00 0.0 0.0 +de - fr 2 263 01/11 22:00 0.0 0.0 +de - fr 2 264 01/11 23:00 0.0 0.0 +de - fr 2 265 01/12 00:00 0.0 0.0 +de - fr 2 266 01/12 01:00 0.0 0.0 +de - fr 2 267 01/12 02:00 0.0 0.0 +de - fr 2 268 01/12 03:00 0.0 0.0 +de - fr 2 269 01/12 04:00 0.0 0.0 +de - fr 2 270 01/12 05:00 0.0 0.0 +de - fr 2 271 01/12 06:00 0.0 0.0 +de - fr 2 272 01/12 07:00 0.0 0.0 +de - fr 2 273 01/12 08:00 0.0 0.0 +de - fr 2 274 01/12 09:00 0.0 0.0 +de - fr 2 275 01/12 10:00 0.0 0.0 +de - fr 2 276 01/12 11:00 0.0 0.0 +de - fr 2 277 01/12 12:00 0.0 0.0 +de - fr 2 278 01/12 13:00 0.0 0.0 +de - fr 2 279 01/12 14:00 0.0 0.0 +de - fr 2 280 01/12 15:00 0.0 0.0 +de - fr 2 281 01/12 16:00 0.0 0.0 +de - fr 2 282 01/12 17:00 0.0 0.0 +de - fr 2 283 01/12 18:00 0.0 0.0 +de - fr 2 284 01/12 19:00 0.0 0.0 +de - fr 2 285 01/12 20:00 0.0 0.0 +de - fr 2 286 01/12 21:00 0.0 0.0 +de - fr 2 287 01/12 22:00 0.0 0.0 +de - fr 2 288 01/12 23:00 0.0 0.0 +de - fr 2 289 01/13 00:00 0.0 0.0 +de - fr 2 290 01/13 01:00 0.0 0.0 +de - fr 2 291 01/13 02:00 0.0 0.0 +de - fr 2 292 01/13 03:00 0.0 0.0 +de - fr 2 293 01/13 04:00 0.0 0.0 +de - fr 2 294 01/13 05:00 0.0 0.0 +de - fr 2 295 01/13 06:00 0.0 0.0 +de - fr 2 296 01/13 07:00 0.0 0.0 +de - fr 2 297 01/13 08:00 0.0 0.0 +de - fr 2 298 01/13 09:00 0.0 0.0 +de - fr 2 299 01/13 10:00 0.0 0.0 +de - fr 2 300 01/13 11:00 0.0 0.0 +de - fr 2 301 01/13 12:00 0.0 0.0 +de - fr 2 302 01/13 13:00 0.0 0.0 +de - fr 2 303 01/13 14:00 0.0 0.0 +de - fr 2 304 01/13 15:00 0.0 0.0 +de - fr 2 305 01/13 16:00 0.0 0.0 +de - fr 2 306 01/13 17:00 0.0 0.0 +de - fr 2 307 01/13 18:00 0.0 0.0 +de - fr 2 308 01/13 19:00 0.0 0.0 +de - fr 2 309 01/13 20:00 0.0 0.0 +de - fr 2 310 01/13 21:00 0.0 0.0 +de - fr 2 311 01/13 22:00 0.0 0.0 +de - fr 2 312 01/13 23:00 0.0 0.0 +de - fr 2 313 01/14 00:00 0.0 0.0 +de - fr 2 314 01/14 01:00 0.0 0.0 +de - fr 2 315 01/14 02:00 0.0 0.0 +de - fr 2 316 01/14 03:00 0.0 0.0 +de - fr 2 317 01/14 04:00 0.0 0.0 +de - fr 2 318 01/14 05:00 0.0 0.0 +de - fr 2 319 01/14 06:00 0.0 0.0 +de - fr 2 320 01/14 07:00 0.0 0.0 +de - fr 2 321 01/14 08:00 0.0 0.0 +de - fr 2 322 01/14 09:00 0.0 0.0 +de - fr 2 323 01/14 10:00 0.0 0.0 +de - fr 2 324 01/14 11:00 0.0 0.0 +de - fr 2 325 01/14 12:00 0.0 0.0 +de - fr 2 326 01/14 13:00 0.0 0.0 +de - fr 2 327 01/14 14:00 0.0 0.0 +de - fr 2 328 01/14 15:00 0.0 0.0 +de - fr 2 329 01/14 16:00 0.0 0.0 +de - fr 2 330 01/14 17:00 0.0 0.0 +de - fr 2 331 01/14 18:00 0.0 0.0 +de - fr 2 332 01/14 19:00 0.0 0.0 +de - fr 2 333 01/14 20:00 0.0 0.0 +de - fr 2 334 01/14 21:00 0.0 0.0 +de - fr 2 335 01/14 22:00 0.0 0.0 +de - fr 2 336 01/14 23:00 0.0 0.0 +es - fr 2 1 01/01 00:00 0.0 0.0 +es - fr 2 2 01/01 01:00 0.0 0.0 +es - fr 2 3 01/01 02:00 0.0 0.0 +es - fr 2 4 01/01 03:00 0.0 0.0 +es - fr 2 5 01/01 04:00 0.0 0.0 +es - fr 2 6 01/01 05:00 0.0 0.0 +es - fr 2 7 01/01 06:00 0.0 0.0 +es - fr 2 8 01/01 07:00 0.0 0.0 +es - fr 2 9 01/01 08:00 0.0 0.0 +es - fr 2 10 01/01 09:00 0.0 0.0 +es - fr 2 11 01/01 10:00 0.0 0.0 +es - fr 2 12 01/01 11:00 0.0 0.0 +es - fr 2 13 01/01 12:00 0.0 0.0 +es - fr 2 14 01/01 13:00 0.0 0.0 +es - fr 2 15 01/01 14:00 0.0 0.0 +es - fr 2 16 01/01 15:00 0.0 0.0 +es - fr 2 17 01/01 16:00 0.0 0.0 +es - fr 2 18 01/01 17:00 0.0 0.0 +es - fr 2 19 01/01 18:00 0.0 0.0 +es - fr 2 20 01/01 19:00 0.0 0.0 +es - fr 2 21 01/01 20:00 0.0 0.0 +es - fr 2 22 01/01 21:00 0.0 0.0 +es - fr 2 23 01/01 22:00 0.0 0.0 +es - fr 2 24 01/01 23:00 0.0 0.0 +es - fr 2 25 01/02 00:00 0.0 0.0 +es - fr 2 26 01/02 01:00 0.0 0.0 +es - fr 2 27 01/02 02:00 0.0 0.0 +es - fr 2 28 01/02 03:00 0.0 0.0 +es - fr 2 29 01/02 04:00 0.0 0.0 +es - fr 2 30 01/02 05:00 0.0 0.0 +es - fr 2 31 01/02 06:00 0.0 0.0 +es - fr 2 32 01/02 07:00 0.0 0.0 +es - fr 2 33 01/02 08:00 0.0 0.0 +es - fr 2 34 01/02 09:00 0.0 0.0 +es - fr 2 35 01/02 10:00 0.0 0.0 +es - fr 2 36 01/02 11:00 0.0 0.0 +es - fr 2 37 01/02 12:00 0.0 0.0 +es - fr 2 38 01/02 13:00 0.0 0.0 +es - fr 2 39 01/02 14:00 0.0 0.0 +es - fr 2 40 01/02 15:00 0.0 0.0 +es - fr 2 41 01/02 16:00 0.0 0.0 +es - fr 2 42 01/02 17:00 0.0 0.0 +es - fr 2 43 01/02 18:00 0.0 0.0 +es - fr 2 44 01/02 19:00 0.0 0.0 +es - fr 2 45 01/02 20:00 0.0 0.0 +es - fr 2 46 01/02 21:00 0.0 0.0 +es - fr 2 47 01/02 22:00 0.0 0.0 +es - fr 2 48 01/02 23:00 0.0 0.0 +es - fr 2 49 01/03 00:00 0.0 0.0 +es - fr 2 50 01/03 01:00 0.0 0.0 +es - fr 2 51 01/03 02:00 0.0 0.0 +es - fr 2 52 01/03 03:00 0.0 0.0 +es - fr 2 53 01/03 04:00 0.0 0.0 +es - fr 2 54 01/03 05:00 0.0 0.0 +es - fr 2 55 01/03 06:00 0.0 0.0 +es - fr 2 56 01/03 07:00 0.0 0.0 +es - fr 2 57 01/03 08:00 0.0 0.0 +es - fr 2 58 01/03 09:00 0.0 0.0 +es - fr 2 59 01/03 10:00 0.0 0.0 +es - fr 2 60 01/03 11:00 0.0 0.0 +es - fr 2 61 01/03 12:00 0.0 0.0 +es - fr 2 62 01/03 13:00 0.0 0.0 +es - fr 2 63 01/03 14:00 0.0 0.0 +es - fr 2 64 01/03 15:00 0.0 0.0 +es - fr 2 65 01/03 16:00 0.0 0.0 +es - fr 2 66 01/03 17:00 0.0 0.0 +es - fr 2 67 01/03 18:00 0.0 0.0 +es - fr 2 68 01/03 19:00 0.0 0.0 +es - fr 2 69 01/03 20:00 0.0 0.0 +es - fr 2 70 01/03 21:00 0.0 0.0 +es - fr 2 71 01/03 22:00 0.0 0.0 +es - fr 2 72 01/03 23:00 0.0 0.0 +es - fr 2 73 01/04 00:00 0.0 0.0 +es - fr 2 74 01/04 01:00 0.0 0.0 +es - fr 2 75 01/04 02:00 0.0 0.0 +es - fr 2 76 01/04 03:00 0.0 0.0 +es - fr 2 77 01/04 04:00 0.0 0.0 +es - fr 2 78 01/04 05:00 0.0 0.0 +es - fr 2 79 01/04 06:00 0.0 0.0 +es - fr 2 80 01/04 07:00 0.0 0.0 +es - fr 2 81 01/04 08:00 0.0 0.0 +es - fr 2 82 01/04 09:00 0.0 0.0 +es - fr 2 83 01/04 10:00 0.0 0.0 +es - fr 2 84 01/04 11:00 0.0 0.0 +es - fr 2 85 01/04 12:00 0.0 0.0 +es - fr 2 86 01/04 13:00 0.0 0.0 +es - fr 2 87 01/04 14:00 0.0 0.0 +es - fr 2 88 01/04 15:00 0.0 0.0 +es - fr 2 89 01/04 16:00 0.0 0.0 +es - fr 2 90 01/04 17:00 0.0 0.0 +es - fr 2 91 01/04 18:00 0.0 0.0 +es - fr 2 92 01/04 19:00 0.0 0.0 +es - fr 2 93 01/04 20:00 0.0 0.0 +es - fr 2 94 01/04 21:00 0.0 0.0 +es - fr 2 95 01/04 22:00 0.0 0.0 +es - fr 2 96 01/04 23:00 0.0 0.0 +es - fr 2 97 01/05 00:00 0.0 0.0 +es - fr 2 98 01/05 01:00 0.0 0.0 +es - fr 2 99 01/05 02:00 0.0 0.0 +es - fr 2 100 01/05 03:00 0.0 0.0 +es - fr 2 101 01/05 04:00 0.0 0.0 +es - fr 2 102 01/05 05:00 0.0 0.0 +es - fr 2 103 01/05 06:00 0.0 0.0 +es - fr 2 104 01/05 07:00 0.0 0.0 +es - fr 2 105 01/05 08:00 0.0 0.0 +es - fr 2 106 01/05 09:00 0.0 0.0 +es - fr 2 107 01/05 10:00 0.0 0.0 +es - fr 2 108 01/05 11:00 0.0 0.0 +es - fr 2 109 01/05 12:00 0.0 0.0 +es - fr 2 110 01/05 13:00 0.0 0.0 +es - fr 2 111 01/05 14:00 0.0 0.0 +es - fr 2 112 01/05 15:00 0.0 0.0 +es - fr 2 113 01/05 16:00 0.0 0.0 +es - fr 2 114 01/05 17:00 0.0 0.0 +es - fr 2 115 01/05 18:00 0.0 0.0 +es - fr 2 116 01/05 19:00 0.0 0.0 +es - fr 2 117 01/05 20:00 0.0 0.0 +es - fr 2 118 01/05 21:00 0.0 0.0 +es - fr 2 119 01/05 22:00 0.0 0.0 +es - fr 2 120 01/05 23:00 0.0 0.0 +es - fr 2 121 01/06 00:00 0.0 0.0 +es - fr 2 122 01/06 01:00 0.0 0.0 +es - fr 2 123 01/06 02:00 0.0 0.0 +es - fr 2 124 01/06 03:00 0.0 0.0 +es - fr 2 125 01/06 04:00 0.0 0.0 +es - fr 2 126 01/06 05:00 0.0 0.0 +es - fr 2 127 01/06 06:00 0.0 0.0 +es - fr 2 128 01/06 07:00 0.0 0.0 +es - fr 2 129 01/06 08:00 0.0 0.0 +es - fr 2 130 01/06 09:00 0.0 0.0 +es - fr 2 131 01/06 10:00 0.0 0.0 +es - fr 2 132 01/06 11:00 0.0 0.0 +es - fr 2 133 01/06 12:00 0.0 0.0 +es - fr 2 134 01/06 13:00 0.0 0.0 +es - fr 2 135 01/06 14:00 0.0 0.0 +es - fr 2 136 01/06 15:00 0.0 0.0 +es - fr 2 137 01/06 16:00 0.0 0.0 +es - fr 2 138 01/06 17:00 0.0 0.0 +es - fr 2 139 01/06 18:00 0.0 0.0 +es - fr 2 140 01/06 19:00 0.0 0.0 +es - fr 2 141 01/06 20:00 0.0 0.0 +es - fr 2 142 01/06 21:00 0.0 0.0 +es - fr 2 143 01/06 22:00 0.0 0.0 +es - fr 2 144 01/06 23:00 0.0 0.0 +es - fr 2 145 01/07 00:00 0.0 0.0 +es - fr 2 146 01/07 01:00 0.0 0.0 +es - fr 2 147 01/07 02:00 0.0 0.0 +es - fr 2 148 01/07 03:00 0.0 0.0 +es - fr 2 149 01/07 04:00 0.0 0.0 +es - fr 2 150 01/07 05:00 0.0 0.0 +es - fr 2 151 01/07 06:00 0.0 0.0 +es - fr 2 152 01/07 07:00 0.0 0.0 +es - fr 2 153 01/07 08:00 0.0 0.0 +es - fr 2 154 01/07 09:00 0.0 0.0 +es - fr 2 155 01/07 10:00 0.0 0.0 +es - fr 2 156 01/07 11:00 0.0 0.0 +es - fr 2 157 01/07 12:00 0.0 0.0 +es - fr 2 158 01/07 13:00 0.0 0.0 +es - fr 2 159 01/07 14:00 0.0 0.0 +es - fr 2 160 01/07 15:00 0.0 0.0 +es - fr 2 161 01/07 16:00 0.0 0.0 +es - fr 2 162 01/07 17:00 0.0 0.0 +es - fr 2 163 01/07 18:00 0.0 0.0 +es - fr 2 164 01/07 19:00 0.0 0.0 +es - fr 2 165 01/07 20:00 0.0 0.0 +es - fr 2 166 01/07 21:00 0.0 0.0 +es - fr 2 167 01/07 22:00 0.0 0.0 +es - fr 2 168 01/07 23:00 0.0 0.0 +es - fr 2 169 01/08 00:00 0.0 0.0 +es - fr 2 170 01/08 01:00 0.0 0.0 +es - fr 2 171 01/08 02:00 0.0 0.0 +es - fr 2 172 01/08 03:00 0.0 0.0 +es - fr 2 173 01/08 04:00 0.0 0.0 +es - fr 2 174 01/08 05:00 0.0 0.0 +es - fr 2 175 01/08 06:00 0.0 0.0 +es - fr 2 176 01/08 07:00 0.0 0.0 +es - fr 2 177 01/08 08:00 0.0 0.0 +es - fr 2 178 01/08 09:00 0.0 0.0 +es - fr 2 179 01/08 10:00 0.0 0.0 +es - fr 2 180 01/08 11:00 0.0 0.0 +es - fr 2 181 01/08 12:00 0.0 0.0 +es - fr 2 182 01/08 13:00 0.0 0.0 +es - fr 2 183 01/08 14:00 0.0 0.0 +es - fr 2 184 01/08 15:00 0.0 0.0 +es - fr 2 185 01/08 16:00 0.0 0.0 +es - fr 2 186 01/08 17:00 0.0 0.0 +es - fr 2 187 01/08 18:00 0.0 0.0 +es - fr 2 188 01/08 19:00 0.0 0.0 +es - fr 2 189 01/08 20:00 0.0 0.0 +es - fr 2 190 01/08 21:00 0.0 0.0 +es - fr 2 191 01/08 22:00 0.0 0.0 +es - fr 2 192 01/08 23:00 0.0 0.0 +es - fr 2 193 01/09 00:00 0.0 0.0 +es - fr 2 194 01/09 01:00 0.0 0.0 +es - fr 2 195 01/09 02:00 0.0 0.0 +es - fr 2 196 01/09 03:00 0.0 0.0 +es - fr 2 197 01/09 04:00 0.0 0.0 +es - fr 2 198 01/09 05:00 0.0 0.0 +es - fr 2 199 01/09 06:00 0.0 0.0 +es - fr 2 200 01/09 07:00 0.0 0.0 +es - fr 2 201 01/09 08:00 0.0 0.0 +es - fr 2 202 01/09 09:00 0.0 0.0 +es - fr 2 203 01/09 10:00 0.0 0.0 +es - fr 2 204 01/09 11:00 0.0 0.0 +es - fr 2 205 01/09 12:00 0.0 0.0 +es - fr 2 206 01/09 13:00 0.0 0.0 +es - fr 2 207 01/09 14:00 0.0 0.0 +es - fr 2 208 01/09 15:00 0.0 0.0 +es - fr 2 209 01/09 16:00 0.0 0.0 +es - fr 2 210 01/09 17:00 0.0 0.0 +es - fr 2 211 01/09 18:00 0.0 0.0 +es - fr 2 212 01/09 19:00 0.0 0.0 +es - fr 2 213 01/09 20:00 0.0 0.0 +es - fr 2 214 01/09 21:00 0.0 0.0 +es - fr 2 215 01/09 22:00 0.0 0.0 +es - fr 2 216 01/09 23:00 0.0 0.0 +es - fr 2 217 01/10 00:00 0.0 0.0 +es - fr 2 218 01/10 01:00 0.0 0.0 +es - fr 2 219 01/10 02:00 0.0 0.0 +es - fr 2 220 01/10 03:00 0.0 0.0 +es - fr 2 221 01/10 04:00 0.0 0.0 +es - fr 2 222 01/10 05:00 0.0 0.0 +es - fr 2 223 01/10 06:00 0.0 0.0 +es - fr 2 224 01/10 07:00 0.0 0.0 +es - fr 2 225 01/10 08:00 0.0 0.0 +es - fr 2 226 01/10 09:00 0.0 0.0 +es - fr 2 227 01/10 10:00 0.0 0.0 +es - fr 2 228 01/10 11:00 0.0 0.0 +es - fr 2 229 01/10 12:00 0.0 0.0 +es - fr 2 230 01/10 13:00 0.0 0.0 +es - fr 2 231 01/10 14:00 0.0 0.0 +es - fr 2 232 01/10 15:00 0.0 0.0 +es - fr 2 233 01/10 16:00 0.0 0.0 +es - fr 2 234 01/10 17:00 0.0 0.0 +es - fr 2 235 01/10 18:00 0.0 0.0 +es - fr 2 236 01/10 19:00 0.0 0.0 +es - fr 2 237 01/10 20:00 0.0 0.0 +es - fr 2 238 01/10 21:00 0.0 0.0 +es - fr 2 239 01/10 22:00 0.0 0.0 +es - fr 2 240 01/10 23:00 0.0 0.0 +es - fr 2 241 01/11 00:00 0.0 0.0 +es - fr 2 242 01/11 01:00 0.0 0.0 +es - fr 2 243 01/11 02:00 0.0 0.0 +es - fr 2 244 01/11 03:00 0.0 0.0 +es - fr 2 245 01/11 04:00 0.0 0.0 +es - fr 2 246 01/11 05:00 0.0 0.0 +es - fr 2 247 01/11 06:00 0.0 0.0 +es - fr 2 248 01/11 07:00 0.0 0.0 +es - fr 2 249 01/11 08:00 0.0 0.0 +es - fr 2 250 01/11 09:00 0.0 0.0 +es - fr 2 251 01/11 10:00 0.0 0.0 +es - fr 2 252 01/11 11:00 0.0 0.0 +es - fr 2 253 01/11 12:00 0.0 0.0 +es - fr 2 254 01/11 13:00 0.0 0.0 +es - fr 2 255 01/11 14:00 0.0 0.0 +es - fr 2 256 01/11 15:00 0.0 0.0 +es - fr 2 257 01/11 16:00 0.0 0.0 +es - fr 2 258 01/11 17:00 0.0 0.0 +es - fr 2 259 01/11 18:00 0.0 0.0 +es - fr 2 260 01/11 19:00 0.0 0.0 +es - fr 2 261 01/11 20:00 0.0 0.0 +es - fr 2 262 01/11 21:00 0.0 0.0 +es - fr 2 263 01/11 22:00 0.0 0.0 +es - fr 2 264 01/11 23:00 0.0 0.0 +es - fr 2 265 01/12 00:00 0.0 0.0 +es - fr 2 266 01/12 01:00 0.0 0.0 +es - fr 2 267 01/12 02:00 0.0 0.0 +es - fr 2 268 01/12 03:00 0.0 0.0 +es - fr 2 269 01/12 04:00 0.0 0.0 +es - fr 2 270 01/12 05:00 0.0 0.0 +es - fr 2 271 01/12 06:00 0.0 0.0 +es - fr 2 272 01/12 07:00 0.0 0.0 +es - fr 2 273 01/12 08:00 0.0 0.0 +es - fr 2 274 01/12 09:00 0.0 0.0 +es - fr 2 275 01/12 10:00 0.0 0.0 +es - fr 2 276 01/12 11:00 0.0 0.0 +es - fr 2 277 01/12 12:00 0.0 0.0 +es - fr 2 278 01/12 13:00 0.0 0.0 +es - fr 2 279 01/12 14:00 0.0 0.0 +es - fr 2 280 01/12 15:00 0.0 0.0 +es - fr 2 281 01/12 16:00 0.0 0.0 +es - fr 2 282 01/12 17:00 0.0 0.0 +es - fr 2 283 01/12 18:00 0.0 0.0 +es - fr 2 284 01/12 19:00 0.0 0.0 +es - fr 2 285 01/12 20:00 0.0 0.0 +es - fr 2 286 01/12 21:00 0.0 0.0 +es - fr 2 287 01/12 22:00 0.0 0.0 +es - fr 2 288 01/12 23:00 0.0 0.0 +es - fr 2 289 01/13 00:00 0.0 0.0 +es - fr 2 290 01/13 01:00 0.0 0.0 +es - fr 2 291 01/13 02:00 0.0 0.0 +es - fr 2 292 01/13 03:00 0.0 0.0 +es - fr 2 293 01/13 04:00 0.0 0.0 +es - fr 2 294 01/13 05:00 0.0 0.0 +es - fr 2 295 01/13 06:00 0.0 0.0 +es - fr 2 296 01/13 07:00 0.0 0.0 +es - fr 2 297 01/13 08:00 0.0 0.0 +es - fr 2 298 01/13 09:00 0.0 0.0 +es - fr 2 299 01/13 10:00 0.0 0.0 +es - fr 2 300 01/13 11:00 0.0 0.0 +es - fr 2 301 01/13 12:00 0.0 0.0 +es - fr 2 302 01/13 13:00 0.0 0.0 +es - fr 2 303 01/13 14:00 0.0 0.0 +es - fr 2 304 01/13 15:00 0.0 0.0 +es - fr 2 305 01/13 16:00 0.0 0.0 +es - fr 2 306 01/13 17:00 0.0 0.0 +es - fr 2 307 01/13 18:00 0.0 0.0 +es - fr 2 308 01/13 19:00 0.0 0.0 +es - fr 2 309 01/13 20:00 0.0 0.0 +es - fr 2 310 01/13 21:00 0.0 0.0 +es - fr 2 311 01/13 22:00 0.0 0.0 +es - fr 2 312 01/13 23:00 0.0 0.0 +es - fr 2 313 01/14 00:00 0.0 0.0 +es - fr 2 314 01/14 01:00 0.0 0.0 +es - fr 2 315 01/14 02:00 0.0 0.0 +es - fr 2 316 01/14 03:00 0.0 0.0 +es - fr 2 317 01/14 04:00 0.0 0.0 +es - fr 2 318 01/14 05:00 0.0 0.0 +es - fr 2 319 01/14 06:00 0.0 0.0 +es - fr 2 320 01/14 07:00 0.0 0.0 +es - fr 2 321 01/14 08:00 0.0 0.0 +es - fr 2 322 01/14 09:00 0.0 0.0 +es - fr 2 323 01/14 10:00 0.0 0.0 +es - fr 2 324 01/14 11:00 0.0 0.0 +es - fr 2 325 01/14 12:00 0.0 0.0 +es - fr 2 326 01/14 13:00 0.0 0.0 +es - fr 2 327 01/14 14:00 0.0 0.0 +es - fr 2 328 01/14 15:00 0.0 0.0 +es - fr 2 329 01/14 16:00 0.0 0.0 +es - fr 2 330 01/14 17:00 0.0 0.0 +es - fr 2 331 01/14 18:00 0.0 0.0 +es - fr 2 332 01/14 19:00 0.0 0.0 +es - fr 2 333 01/14 20:00 0.0 0.0 +es - fr 2 334 01/14 21:00 0.0 0.0 +es - fr 2 335 01/14 22:00 0.0 0.0 +es - fr 2 336 01/14 23:00 0.0 0.0 +fr - it 2 1 01/01 00:00 0.0 0.0 +fr - it 2 2 01/01 01:00 0.0 0.0 +fr - it 2 3 01/01 02:00 0.0 0.0 +fr - it 2 4 01/01 03:00 0.0 0.0 +fr - it 2 5 01/01 04:00 0.0 0.0 +fr - it 2 6 01/01 05:00 0.0 0.0 +fr - it 2 7 01/01 06:00 0.0 0.0 +fr - it 2 8 01/01 07:00 0.0 0.0 +fr - it 2 9 01/01 08:00 0.0 0.0 +fr - it 2 10 01/01 09:00 0.0 0.0 +fr - it 2 11 01/01 10:00 0.0 0.0 +fr - it 2 12 01/01 11:00 0.0 0.0 +fr - it 2 13 01/01 12:00 0.0 0.0 +fr - it 2 14 01/01 13:00 0.0 0.0 +fr - it 2 15 01/01 14:00 0.0 0.0 +fr - it 2 16 01/01 15:00 0.0 0.0 +fr - it 2 17 01/01 16:00 0.0 0.0 +fr - it 2 18 01/01 17:00 0.0 0.0 +fr - it 2 19 01/01 18:00 0.0 0.0 +fr - it 2 20 01/01 19:00 0.0 0.0 +fr - it 2 21 01/01 20:00 0.0 0.0 +fr - it 2 22 01/01 21:00 0.0 0.0 +fr - it 2 23 01/01 22:00 0.0 0.0 +fr - it 2 24 01/01 23:00 0.0 0.0 +fr - it 2 25 01/02 00:00 0.0 0.0 +fr - it 2 26 01/02 01:00 0.0 0.0 +fr - it 2 27 01/02 02:00 0.0 0.0 +fr - it 2 28 01/02 03:00 0.0 0.0 +fr - it 2 29 01/02 04:00 0.0 0.0 +fr - it 2 30 01/02 05:00 0.0 0.0 +fr - it 2 31 01/02 06:00 0.0 0.0 +fr - it 2 32 01/02 07:00 0.0 0.0 +fr - it 2 33 01/02 08:00 0.0 0.0 +fr - it 2 34 01/02 09:00 0.0 0.0 +fr - it 2 35 01/02 10:00 0.0 0.0 +fr - it 2 36 01/02 11:00 0.0 0.0 +fr - it 2 37 01/02 12:00 0.0 0.0 +fr - it 2 38 01/02 13:00 0.0 0.0 +fr - it 2 39 01/02 14:00 0.0 0.0 +fr - it 2 40 01/02 15:00 0.0 0.0 +fr - it 2 41 01/02 16:00 0.0 0.0 +fr - it 2 42 01/02 17:00 0.0 0.0 +fr - it 2 43 01/02 18:00 0.0 0.0 +fr - it 2 44 01/02 19:00 0.0 0.0 +fr - it 2 45 01/02 20:00 0.0 0.0 +fr - it 2 46 01/02 21:00 0.0 0.0 +fr - it 2 47 01/02 22:00 0.0 0.0 +fr - it 2 48 01/02 23:00 0.0 0.0 +fr - it 2 49 01/03 00:00 0.0 0.0 +fr - it 2 50 01/03 01:00 0.0 0.0 +fr - it 2 51 01/03 02:00 0.0 0.0 +fr - it 2 52 01/03 03:00 0.0 0.0 +fr - it 2 53 01/03 04:00 0.0 0.0 +fr - it 2 54 01/03 05:00 0.0 0.0 +fr - it 2 55 01/03 06:00 0.0 0.0 +fr - it 2 56 01/03 07:00 0.0 0.0 +fr - it 2 57 01/03 08:00 0.0 0.0 +fr - it 2 58 01/03 09:00 0.0 0.0 +fr - it 2 59 01/03 10:00 0.0 0.0 +fr - it 2 60 01/03 11:00 0.0 0.0 +fr - it 2 61 01/03 12:00 0.0 0.0 +fr - it 2 62 01/03 13:00 0.0 0.0 +fr - it 2 63 01/03 14:00 0.0 0.0 +fr - it 2 64 01/03 15:00 0.0 0.0 +fr - it 2 65 01/03 16:00 0.0 0.0 +fr - it 2 66 01/03 17:00 0.0 0.0 +fr - it 2 67 01/03 18:00 0.0 0.0 +fr - it 2 68 01/03 19:00 0.0 0.0 +fr - it 2 69 01/03 20:00 0.0 0.0 +fr - it 2 70 01/03 21:00 0.0 0.0 +fr - it 2 71 01/03 22:00 0.0 0.0 +fr - it 2 72 01/03 23:00 0.0 0.0 +fr - it 2 73 01/04 00:00 0.0 0.0 +fr - it 2 74 01/04 01:00 0.0 0.0 +fr - it 2 75 01/04 02:00 0.0 0.0 +fr - it 2 76 01/04 03:00 0.0 0.0 +fr - it 2 77 01/04 04:00 0.0 0.0 +fr - it 2 78 01/04 05:00 0.0 0.0 +fr - it 2 79 01/04 06:00 0.0 0.0 +fr - it 2 80 01/04 07:00 0.0 0.0 +fr - it 2 81 01/04 08:00 0.0 0.0 +fr - it 2 82 01/04 09:00 0.0 0.0 +fr - it 2 83 01/04 10:00 0.0 0.0 +fr - it 2 84 01/04 11:00 0.0 0.0 +fr - it 2 85 01/04 12:00 0.0 0.0 +fr - it 2 86 01/04 13:00 0.0 0.0 +fr - it 2 87 01/04 14:00 0.0 0.0 +fr - it 2 88 01/04 15:00 0.0 0.0 +fr - it 2 89 01/04 16:00 0.0 0.0 +fr - it 2 90 01/04 17:00 0.0 0.0 +fr - it 2 91 01/04 18:00 0.0 0.0 +fr - it 2 92 01/04 19:00 0.0 0.0 +fr - it 2 93 01/04 20:00 0.0 0.0 +fr - it 2 94 01/04 21:00 0.0 0.0 +fr - it 2 95 01/04 22:00 0.0 0.0 +fr - it 2 96 01/04 23:00 0.0 0.0 +fr - it 2 97 01/05 00:00 0.0 0.0 +fr - it 2 98 01/05 01:00 0.0 0.0 +fr - it 2 99 01/05 02:00 0.0 0.0 +fr - it 2 100 01/05 03:00 0.0 0.0 +fr - it 2 101 01/05 04:00 0.0 0.0 +fr - it 2 102 01/05 05:00 0.0 0.0 +fr - it 2 103 01/05 06:00 0.0 0.0 +fr - it 2 104 01/05 07:00 0.0 0.0 +fr - it 2 105 01/05 08:00 0.0 0.0 +fr - it 2 106 01/05 09:00 0.0 0.0 +fr - it 2 107 01/05 10:00 0.0 0.0 +fr - it 2 108 01/05 11:00 0.0 0.0 +fr - it 2 109 01/05 12:00 0.0 0.0 +fr - it 2 110 01/05 13:00 0.0 0.0 +fr - it 2 111 01/05 14:00 0.0 0.0 +fr - it 2 112 01/05 15:00 0.0 0.0 +fr - it 2 113 01/05 16:00 0.0 0.0 +fr - it 2 114 01/05 17:00 0.0 0.0 +fr - it 2 115 01/05 18:00 0.0 0.0 +fr - it 2 116 01/05 19:00 0.0 0.0 +fr - it 2 117 01/05 20:00 0.0 0.0 +fr - it 2 118 01/05 21:00 0.0 0.0 +fr - it 2 119 01/05 22:00 0.0 0.0 +fr - it 2 120 01/05 23:00 0.0 0.0 +fr - it 2 121 01/06 00:00 0.0 0.0 +fr - it 2 122 01/06 01:00 0.0 0.0 +fr - it 2 123 01/06 02:00 0.0 0.0 +fr - it 2 124 01/06 03:00 0.0 0.0 +fr - it 2 125 01/06 04:00 0.0 0.0 +fr - it 2 126 01/06 05:00 0.0 0.0 +fr - it 2 127 01/06 06:00 0.0 0.0 +fr - it 2 128 01/06 07:00 0.0 0.0 +fr - it 2 129 01/06 08:00 0.0 0.0 +fr - it 2 130 01/06 09:00 0.0 0.0 +fr - it 2 131 01/06 10:00 0.0 0.0 +fr - it 2 132 01/06 11:00 0.0 0.0 +fr - it 2 133 01/06 12:00 0.0 0.0 +fr - it 2 134 01/06 13:00 0.0 0.0 +fr - it 2 135 01/06 14:00 0.0 0.0 +fr - it 2 136 01/06 15:00 0.0 0.0 +fr - it 2 137 01/06 16:00 0.0 0.0 +fr - it 2 138 01/06 17:00 0.0 0.0 +fr - it 2 139 01/06 18:00 0.0 0.0 +fr - it 2 140 01/06 19:00 0.0 0.0 +fr - it 2 141 01/06 20:00 0.0 0.0 +fr - it 2 142 01/06 21:00 0.0 0.0 +fr - it 2 143 01/06 22:00 0.0 0.0 +fr - it 2 144 01/06 23:00 0.0 0.0 +fr - it 2 145 01/07 00:00 0.0 0.0 +fr - it 2 146 01/07 01:00 0.0 0.0 +fr - it 2 147 01/07 02:00 0.0 0.0 +fr - it 2 148 01/07 03:00 0.0 0.0 +fr - it 2 149 01/07 04:00 0.0 0.0 +fr - it 2 150 01/07 05:00 0.0 0.0 +fr - it 2 151 01/07 06:00 0.0 0.0 +fr - it 2 152 01/07 07:00 0.0 0.0 +fr - it 2 153 01/07 08:00 0.0 0.0 +fr - it 2 154 01/07 09:00 0.0 0.0 +fr - it 2 155 01/07 10:00 0.0 0.0 +fr - it 2 156 01/07 11:00 0.0 0.0 +fr - it 2 157 01/07 12:00 0.0 0.0 +fr - it 2 158 01/07 13:00 0.0 0.0 +fr - it 2 159 01/07 14:00 0.0 0.0 +fr - it 2 160 01/07 15:00 0.0 0.0 +fr - it 2 161 01/07 16:00 0.0 0.0 +fr - it 2 162 01/07 17:00 0.0 0.0 +fr - it 2 163 01/07 18:00 0.0 0.0 +fr - it 2 164 01/07 19:00 0.0 0.0 +fr - it 2 165 01/07 20:00 0.0 0.0 +fr - it 2 166 01/07 21:00 0.0 0.0 +fr - it 2 167 01/07 22:00 0.0 0.0 +fr - it 2 168 01/07 23:00 0.0 0.0 +fr - it 2 169 01/08 00:00 0.0 0.0 +fr - it 2 170 01/08 01:00 0.0 0.0 +fr - it 2 171 01/08 02:00 0.0 0.0 +fr - it 2 172 01/08 03:00 0.0 0.0 +fr - it 2 173 01/08 04:00 0.0 0.0 +fr - it 2 174 01/08 05:00 0.0 0.0 +fr - it 2 175 01/08 06:00 0.0 0.0 +fr - it 2 176 01/08 07:00 0.0 0.0 +fr - it 2 177 01/08 08:00 0.0 0.0 +fr - it 2 178 01/08 09:00 0.0 0.0 +fr - it 2 179 01/08 10:00 0.0 0.0 +fr - it 2 180 01/08 11:00 0.0 0.0 +fr - it 2 181 01/08 12:00 0.0 0.0 +fr - it 2 182 01/08 13:00 0.0 0.0 +fr - it 2 183 01/08 14:00 0.0 0.0 +fr - it 2 184 01/08 15:00 0.0 0.0 +fr - it 2 185 01/08 16:00 0.0 0.0 +fr - it 2 186 01/08 17:00 0.0 0.0 +fr - it 2 187 01/08 18:00 0.0 0.0 +fr - it 2 188 01/08 19:00 0.0 0.0 +fr - it 2 189 01/08 20:00 0.0 0.0 +fr - it 2 190 01/08 21:00 0.0 0.0 +fr - it 2 191 01/08 22:00 0.0 0.0 +fr - it 2 192 01/08 23:00 0.0 0.0 +fr - it 2 193 01/09 00:00 0.0 0.0 +fr - it 2 194 01/09 01:00 0.0 0.0 +fr - it 2 195 01/09 02:00 0.0 0.0 +fr - it 2 196 01/09 03:00 0.0 0.0 +fr - it 2 197 01/09 04:00 0.0 0.0 +fr - it 2 198 01/09 05:00 0.0 0.0 +fr - it 2 199 01/09 06:00 0.0 0.0 +fr - it 2 200 01/09 07:00 0.0 0.0 +fr - it 2 201 01/09 08:00 0.0 0.0 +fr - it 2 202 01/09 09:00 0.0 0.0 +fr - it 2 203 01/09 10:00 0.0 0.0 +fr - it 2 204 01/09 11:00 0.0 0.0 +fr - it 2 205 01/09 12:00 0.0 0.0 +fr - it 2 206 01/09 13:00 0.0 0.0 +fr - it 2 207 01/09 14:00 0.0 0.0 +fr - it 2 208 01/09 15:00 0.0 0.0 +fr - it 2 209 01/09 16:00 0.0 0.0 +fr - it 2 210 01/09 17:00 0.0 0.0 +fr - it 2 211 01/09 18:00 0.0 0.0 +fr - it 2 212 01/09 19:00 0.0 0.0 +fr - it 2 213 01/09 20:00 0.0 0.0 +fr - it 2 214 01/09 21:00 0.0 0.0 +fr - it 2 215 01/09 22:00 0.0 0.0 +fr - it 2 216 01/09 23:00 0.0 0.0 +fr - it 2 217 01/10 00:00 0.0 0.0 +fr - it 2 218 01/10 01:00 0.0 0.0 +fr - it 2 219 01/10 02:00 0.0 0.0 +fr - it 2 220 01/10 03:00 0.0 0.0 +fr - it 2 221 01/10 04:00 0.0 0.0 +fr - it 2 222 01/10 05:00 0.0 0.0 +fr - it 2 223 01/10 06:00 0.0 0.0 +fr - it 2 224 01/10 07:00 0.0 0.0 +fr - it 2 225 01/10 08:00 0.0 0.0 +fr - it 2 226 01/10 09:00 0.0 0.0 +fr - it 2 227 01/10 10:00 0.0 0.0 +fr - it 2 228 01/10 11:00 0.0 0.0 +fr - it 2 229 01/10 12:00 0.0 0.0 +fr - it 2 230 01/10 13:00 0.0 0.0 +fr - it 2 231 01/10 14:00 0.0 0.0 +fr - it 2 232 01/10 15:00 0.0 0.0 +fr - it 2 233 01/10 16:00 0.0 0.0 +fr - it 2 234 01/10 17:00 0.0 0.0 +fr - it 2 235 01/10 18:00 0.0 0.0 +fr - it 2 236 01/10 19:00 0.0 0.0 +fr - it 2 237 01/10 20:00 0.0 0.0 +fr - it 2 238 01/10 21:00 0.0 0.0 +fr - it 2 239 01/10 22:00 0.0 0.0 +fr - it 2 240 01/10 23:00 0.0 0.0 +fr - it 2 241 01/11 00:00 0.0 0.0 +fr - it 2 242 01/11 01:00 0.0 0.0 +fr - it 2 243 01/11 02:00 0.0 0.0 +fr - it 2 244 01/11 03:00 0.0 0.0 +fr - it 2 245 01/11 04:00 0.0 0.0 +fr - it 2 246 01/11 05:00 0.0 0.0 +fr - it 2 247 01/11 06:00 0.0 0.0 +fr - it 2 248 01/11 07:00 0.0 0.0 +fr - it 2 249 01/11 08:00 0.0 0.0 +fr - it 2 250 01/11 09:00 0.0 0.0 +fr - it 2 251 01/11 10:00 0.0 0.0 +fr - it 2 252 01/11 11:00 0.0 0.0 +fr - it 2 253 01/11 12:00 0.0 0.0 +fr - it 2 254 01/11 13:00 0.0 0.0 +fr - it 2 255 01/11 14:00 0.0 0.0 +fr - it 2 256 01/11 15:00 0.0 0.0 +fr - it 2 257 01/11 16:00 0.0 0.0 +fr - it 2 258 01/11 17:00 0.0 0.0 +fr - it 2 259 01/11 18:00 0.0 0.0 +fr - it 2 260 01/11 19:00 0.0 0.0 +fr - it 2 261 01/11 20:00 0.0 0.0 +fr - it 2 262 01/11 21:00 0.0 0.0 +fr - it 2 263 01/11 22:00 0.0 0.0 +fr - it 2 264 01/11 23:00 0.0 0.0 +fr - it 2 265 01/12 00:00 0.0 0.0 +fr - it 2 266 01/12 01:00 0.0 0.0 +fr - it 2 267 01/12 02:00 0.0 0.0 +fr - it 2 268 01/12 03:00 0.0 0.0 +fr - it 2 269 01/12 04:00 0.0 0.0 +fr - it 2 270 01/12 05:00 0.0 0.0 +fr - it 2 271 01/12 06:00 0.0 0.0 +fr - it 2 272 01/12 07:00 0.0 0.0 +fr - it 2 273 01/12 08:00 0.0 0.0 +fr - it 2 274 01/12 09:00 0.0 0.0 +fr - it 2 275 01/12 10:00 0.0 0.0 +fr - it 2 276 01/12 11:00 0.0 0.0 +fr - it 2 277 01/12 12:00 0.0 0.0 +fr - it 2 278 01/12 13:00 0.0 0.0 +fr - it 2 279 01/12 14:00 0.0 0.0 +fr - it 2 280 01/12 15:00 0.0 0.0 +fr - it 2 281 01/12 16:00 0.0 0.0 +fr - it 2 282 01/12 17:00 0.0 0.0 +fr - it 2 283 01/12 18:00 0.0 0.0 +fr - it 2 284 01/12 19:00 0.0 0.0 +fr - it 2 285 01/12 20:00 0.0 0.0 +fr - it 2 286 01/12 21:00 0.0 0.0 +fr - it 2 287 01/12 22:00 0.0 0.0 +fr - it 2 288 01/12 23:00 0.0 0.0 +fr - it 2 289 01/13 00:00 0.0 0.0 +fr - it 2 290 01/13 01:00 0.0 0.0 +fr - it 2 291 01/13 02:00 0.0 0.0 +fr - it 2 292 01/13 03:00 0.0 0.0 +fr - it 2 293 01/13 04:00 0.0 0.0 +fr - it 2 294 01/13 05:00 0.0 0.0 +fr - it 2 295 01/13 06:00 0.0 0.0 +fr - it 2 296 01/13 07:00 0.0 0.0 +fr - it 2 297 01/13 08:00 0.0 0.0 +fr - it 2 298 01/13 09:00 0.0 0.0 +fr - it 2 299 01/13 10:00 0.0 0.0 +fr - it 2 300 01/13 11:00 0.0 0.0 +fr - it 2 301 01/13 12:00 0.0 0.0 +fr - it 2 302 01/13 13:00 0.0 0.0 +fr - it 2 303 01/13 14:00 0.0 0.0 +fr - it 2 304 01/13 15:00 0.0 0.0 +fr - it 2 305 01/13 16:00 0.0 0.0 +fr - it 2 306 01/13 17:00 0.0 0.0 +fr - it 2 307 01/13 18:00 0.0 0.0 +fr - it 2 308 01/13 19:00 0.0 0.0 +fr - it 2 309 01/13 20:00 0.0 0.0 +fr - it 2 310 01/13 21:00 0.0 0.0 +fr - it 2 311 01/13 22:00 0.0 0.0 +fr - it 2 312 01/13 23:00 0.0 0.0 +fr - it 2 313 01/14 00:00 0.0 0.0 +fr - it 2 314 01/14 01:00 0.0 0.0 +fr - it 2 315 01/14 02:00 0.0 0.0 +fr - it 2 316 01/14 03:00 0.0 0.0 +fr - it 2 317 01/14 04:00 0.0 0.0 +fr - it 2 318 01/14 05:00 0.0 0.0 +fr - it 2 319 01/14 06:00 0.0 0.0 +fr - it 2 320 01/14 07:00 0.0 0.0 +fr - it 2 321 01/14 08:00 0.0 0.0 +fr - it 2 322 01/14 09:00 0.0 0.0 +fr - it 2 323 01/14 10:00 0.0 0.0 +fr - it 2 324 01/14 11:00 0.0 0.0 +fr - it 2 325 01/14 12:00 0.0 0.0 +fr - it 2 326 01/14 13:00 0.0 0.0 +fr - it 2 327 01/14 14:00 0.0 0.0 +fr - it 2 328 01/14 15:00 0.0 0.0 +fr - it 2 329 01/14 16:00 0.0 0.0 +fr - it 2 330 01/14 17:00 0.0 0.0 +fr - it 2 331 01/14 18:00 0.0 0.0 +fr - it 2 332 01/14 19:00 0.0 0.0 +fr - it 2 333 01/14 20:00 0.0 0.0 +fr - it 2 334 01/14 21:00 0.0 0.0 +fr - it 2 335 01/14 22:00 0.0 0.0 +fr - it 2 336 01/14 23:00 0.0 0.0 diff --git a/tests/integration/raw_studies_blueprint/test_aggregate_raw_data.py b/tests/integration/raw_studies_blueprint/test_aggregate_raw_data.py new file mode 100644 index 0000000000..4f449d8fc2 --- /dev/null +++ b/tests/integration/raw_studies_blueprint/test_aggregate_raw_data.py @@ -0,0 +1,196 @@ +import typing as t + +import numpy as np +import pandas as pd +import pytest +from starlette.testclient import TestClient + +from antarest.study.common.default_values import AreasQueryFile, LinksQueryFile +from antarest.study.storage.rawstudy.model.filesystem.matrix.matrix import MatrixFrequency +from tests.integration.raw_studies_blueprint.assets import ASSETS_DIR + + +@pytest.mark.integration_test +class TestRawDataAggregation: + """ + Check the aggregation of Raw Data from studies outputs + """ + + @pytest.mark.parametrize( + "params, expected_result_filename", + [ + ( + { + "output_id": "20201014-1425eco-goodbye", + "query_file": AreasQueryFile.VALUES, + "frequency": MatrixFrequency.HOURLY, + "mc_years": "", + "areas_ids": "", + "columns_names": "", + }, + "test-01.result.tsv", + ), + ( + { + "output_id": "20201014-1425eco-goodbye", + "query_file": AreasQueryFile.DETAILS, + "frequency": MatrixFrequency.HOURLY, + "mc_years": "1", + "areas_ids": "de,fr,it", + "columns_names": "", + }, + "test-02.result.tsv", + ), + ( + { + "output_id": "20201014-1425eco-goodbye", + "query_file": AreasQueryFile.VALUES, + "frequency": MatrixFrequency.WEEKLY, + "mc_years": "1,2", + "areas_ids": "", + "columns_names": "OP. COST,MRG. PRICE", + }, + "test-03.result.tsv", + ), + ( + { + "output_id": "20201014-1425eco-goodbye", + "query_file": AreasQueryFile.VALUES, + "frequency": MatrixFrequency.HOURLY, + "mc_years": "2", + "areas_ids": "es,fr,de", + "columns_names": "", + }, + "test-04.result.tsv", + ), + ( + { + "output_id": "20201014-1425eco-goodbye", + "query_file": AreasQueryFile.VALUES, + "frequency": MatrixFrequency.ANNUAL, + "mc_years": "", + "areas_ids": "", + "columns_names": "", + }, + "test-05.result.tsv", + ), + ], + ) + def test_area_aggregation( + self, + client: TestClient, + user_access_token: str, + study_id: str, + params: t.Dict[str, t.Any], + expected_result_filename: str, + ): + """ + Test the aggregation of areas data + """ + headers = {"Authorization": f"Bearer {user_access_token}"} + + res = client.get( + f"/v1/studies/{study_id}/areas/aggregate", + params=params, + headers=headers, + ) + assert res.status_code == 200 + matrix = res.json() + df = pd.DataFrame(**matrix) + resource_file = ASSETS_DIR.joinpath(f"aggregate_areas_raw_data/{expected_result_filename}") + resource_file.parent.mkdir(exist_ok=True, parents=True) + if resource_file.exists(): + # compare with previous result (non-regression test) + expected_df = pd.read_csv(resource_file, sep="\t", header=0) + expected_df = expected_df.replace({np.nan: None}) + # cast types of expected_df to match df + for col in expected_df.columns: + expected_df[col] = expected_df[col].astype(df[col].dtype) + pd.testing.assert_frame_equal(df, expected_df) + else: + # create the resource + df.to_csv(resource_file, sep="\t", index=False) + if params["areas_ids"] and matrix["columns"]: + assert not (set(df["area"].values) - set(params["areas_ids"].split(","))) + if params["mc_years"] and matrix["columns"]: + assert not (set(df["mcYear"].values) - set(int(i) for i in params["mc_years"].split(","))) + if params["columns_names"] and matrix["columns"]: + assert not ( + set(df.columns.values) - {"area", "mcYear", "timeId", "time"} - set(params["columns_names"].split(",")) + ) + + @pytest.mark.parametrize( + "params, expected_result_filename", + [ + ( + { + "output_id": "20201014-1425eco-goodbye", + "query_file": LinksQueryFile.VALUES, + "frequency": MatrixFrequency.HOURLY, + "mc_years": "", + "columns_names": "", + }, + "test-01.result.tsv", + ), + ( + { + "output_id": "20201014-1425eco-goodbye", + "query_file": LinksQueryFile.VALUES, + "frequency": MatrixFrequency.HOURLY, + "mc_years": "1", + "columns_names": "", + }, + "test-02.result.tsv", + ), + ( + { + "output_id": "20201014-1425eco-goodbye", + "query_file": LinksQueryFile.VALUES, + "frequency": MatrixFrequency.HOURLY, + "mc_years": "1,2", + "columns_names": "UCAP LIN.,FLOW QUAD.", + }, + "test-03.result.tsv", + ), + ], + ) + def test_links_aggregation( + self, + client: TestClient, + user_access_token: str, + study_id: str, + params: t.Dict[str, t.Any], + expected_result_filename: str, + ): + """ + Test the aggregation of links data + """ + headers = {"Authorization": f"Bearer {user_access_token}"} + + res = client.get( + f"/v1/studies/{study_id}/links/aggregate", + params=params, + headers=headers, + ) + assert res.status_code == 200 + matrix = res.json() + df = pd.DataFrame(**matrix) + resource_file = ASSETS_DIR.joinpath(f"aggregate_links_raw_data/{expected_result_filename}") + resource_file.parent.mkdir(exist_ok=True, parents=True) + if resource_file.exists(): + # compare with previous result (non-regression test) + expected_df = pd.read_csv(resource_file, sep="\t", header=0) + expected_df = expected_df.replace({np.nan: None}) + # cast types of expected_df to match df + for col in expected_df.columns: + expected_df[col] = expected_df[col].astype(df[col].dtype) + pd.testing.assert_frame_equal(df, expected_df) + else: + # create the resource + df.to_csv(resource_file, sep="\t", index=False) + if params["mc_years"] and matrix["columns"]: + assert not (set(df["mcYear"].values) - set(int(i) for i in params["mc_years"].split(","))) + if params["columns_names"] and matrix["columns"]: + assert not ( + set(df.columns.values) - {"link", "mcYear", "timeId", "time"} - set(params["columns_names"].split(",")) + ) diff --git a/tests/integration/raw_studies_blueprint/test_download_matrices.py b/tests/integration/raw_studies_blueprint/test_download_matrices.py new file mode 100644 index 0000000000..0fcf2683c5 --- /dev/null +++ b/tests/integration/raw_studies_blueprint/test_download_matrices.py @@ -0,0 +1,402 @@ +import datetime +import io +import typing as t + +import numpy as np +import pandas as pd +import pytest +from starlette.testclient import TestClient + +from antarest.core.tasks.model import TaskStatus +from tests.integration.utils import wait_task_completion + + +class Proxy: + def __init__(self, client: TestClient, user_access_token: str): + self.client = client + self.user_access_token = user_access_token + self.headers = {"Authorization": f"Bearer {user_access_token}"} + + +class PreparerProxy(Proxy): + def copy_upgrade_study(self, ref_study_id, target_version=820): + """ + Copy a study in the managed workspace and upgrade it to a specific version + """ + # Prepare a managed study to test specific matrices for version 8.2 + res = self.client.post( + f"/v1/studies/{ref_study_id}/copy", + params={"dest": "copied-820", "use_task": False}, + headers=self.headers, + ) + res.raise_for_status() + study_820_id = res.json() + + res = self.client.put( + f"/v1/studies/{study_820_id}/upgrade", + params={"target_version": target_version}, + headers=self.headers, + ) + res.raise_for_status() + task_id = res.json() + assert task_id + + task = wait_task_completion(self.client, self.user_access_token, task_id, timeout=20) + assert task.status == TaskStatus.COMPLETED + return study_820_id + + def upload_matrix(self, study_id: str, matrix_path: str, df: pd.DataFrame) -> None: + tsv = io.BytesIO() + df.to_csv(tsv, sep="\t", index=False, header=False) + tsv.seek(0) + # noinspection SpellCheckingInspection + res = self.client.put( + f"/v1/studies/{study_id}/raw", + params={"path": matrix_path, "create_missing": True}, + headers=self.headers, + files={"file": tsv, "create_missing": "true"}, + ) + res.raise_for_status() + + def create_variant(self, parent_id: str, *, name: str) -> str: + res = self.client.post( + f"/v1/studies/{parent_id}/variants", + headers=self.headers, + params={"name": name}, + ) + res.raise_for_status() + variant_id = res.json() + return variant_id + + def generate_snapshot(self, variant_id: str, denormalize=False, from_scratch=True) -> None: + # Generate a snapshot for the variant + res = self.client.put( + f"/v1/studies/{variant_id}/generate", + headers=self.headers, + params={"denormalize": denormalize, "from_scratch": from_scratch}, + ) + res.raise_for_status() + task_id = res.json() + assert task_id + + task = wait_task_completion(self.client, self.user_access_token, task_id, timeout=20) + assert task.status == TaskStatus.COMPLETED + + def create_area(self, parent_id, *, name: str, country: str = "FR") -> str: + res = self.client.post( + f"/v1/studies/{parent_id}/areas", + headers=self.headers, + json={"name": name, "type": "AREA", "metadata": {"country": country}}, + ) + res.raise_for_status() + area_id = res.json()["id"] + return area_id + + def update_general_data(self, study_id: str, **data: t.Any): + res = self.client.put( + f"/v1/studies/{study_id}/config/general/form", + json=data, + headers=self.headers, + ) + res.raise_for_status() + + +@pytest.mark.integration_test +class TestDownloadMatrices: + """ + Checks the retrieval of matrices with the endpoint GET studies/uuid/raw/download + """ + + def test_download_matrices(self, client: TestClient, user_access_token: str, study_id: str) -> None: + user_headers = {"Authorization": f"Bearer {user_access_token}"} + + # ===================== + # STUDIES PREPARATION + # ===================== + + preparer = PreparerProxy(client, user_access_token) + + study_820_id = preparer.copy_upgrade_study(study_id, target_version=820) + + # Create Variant + variant_id = preparer.create_variant(study_820_id, name="New Variant") + + # Create a new area to implicitly create normalized matrices + area_id = preparer.create_area(variant_id, name="Mayenne", country="France") + + # Change study start_date + preparer.update_general_data(variant_id, firstMonth="July") + + # Really generates the snapshot + preparer.generate_snapshot(variant_id) + + # Prepare a managed study to test specific matrices for version 8.6 + study_860_id = preparer.copy_upgrade_study(study_id, target_version=860) + + # Import a Min Gen. matrix: shape=(8760, 3), with random integers between 0 and 1000 + min_gen_df = pd.DataFrame(np.random.randint(0, 1000, size=(8760, 3))) + preparer.upload_matrix(study_860_id, "input/hydro/series/de/mingen", min_gen_df) + + # ============================================= + # TESTS NOMINAL CASE ON RAW AND VARIANT STUDY + # ============================================= + + raw_matrix_path = r"input/load/series/load_de" + variant_matrix_path = f"input/load/series/load_{area_id}" + + raw_start_date = datetime.datetime(2018, 1, 1) + variant_start_date = datetime.datetime(2019, 7, 1) + + for uuid, path, start_date in [ + (study_820_id, raw_matrix_path, raw_start_date), + (variant_id, variant_matrix_path, variant_start_date), + ]: + # Export the matrix in xlsx format (which is the default format) + # and retrieve it as binary content (a ZIP-like file). + res = client.get( + f"/v1/studies/{uuid}/raw/download", + params={"path": path}, + headers=user_headers, + ) + assert res.status_code == 200 + # noinspection SpellCheckingInspection + assert res.headers["content-type"] == ( + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=utf-8" + ) + + # load into dataframe + # noinspection PyTypeChecker + dataframe = pd.read_excel(io.BytesIO(res.content), index_col=0) + + # check time coherence + actual_index = dataframe.index + # noinspection PyUnresolvedReferences + first_date = actual_index[0].to_pydatetime() + # noinspection PyUnresolvedReferences + second_date = actual_index[1].to_pydatetime() + first_month = 1 if uuid == study_820_id else 7 # July + assert first_date.month == second_date.month == first_month + assert first_date.day == second_date.day == 1 + assert first_date.hour == 0 + assert second_date.hour == 1 + + # asserts that the result is the same as the one we get with the classic get /raw endpoint + res = client.get( + f"/v1/studies/{uuid}/raw", + params={"path": path, "formatted": True}, + headers=user_headers, + ) + expected_matrix = res.json() + expected_matrix["columns"] = [f"TS-{n + 1}" for n in expected_matrix["columns"]] + time_column = pd.date_range( + start=start_date, + periods=len(expected_matrix["data"]), + freq="H", + ) + expected_matrix["index"] = time_column + expected = pd.DataFrame(**expected_matrix) + assert dataframe.index.tolist() == expected.index.tolist() + assert dataframe.columns.tolist() == expected.columns.tolist() + assert (dataframe == expected).all().all() + + # ============================= + # TESTS INDEX AND HEADER PARAMETERS + # ============================= + + # test only few possibilities as each API call is quite long + # (also check that the format is case-insensitive) + for header in [True, False]: + index = not header + res = client.get( + f"/v1/studies/{study_820_id}/raw/download", + params={"path": raw_matrix_path, "format": "TSV", "header": header, "index": index}, + headers=user_headers, + ) + assert res.status_code == 200 + assert res.headers["content-type"] == "text/tab-separated-values; charset=utf-8" + + content = io.BytesIO(res.content) + dataframe = pd.read_csv( + content, index_col=0 if index else None, header="infer" if header else None, sep="\t" + ) + first_index = dataframe.index[0] + assert first_index == "2018-01-01 00:00:00" if index else first_index == 0 + assert isinstance(dataframe.columns[0], str) if header else isinstance(dataframe.columns[0], np.int64) + + # ============================= + # TEST SPECIFIC MATRICES + # ============================= + + # tests links headers before v8.2 + res = client.get( + f"/v1/studies/{study_id}/raw/download", + params={"path": "input/links/de/fr", "format": "tsv", "index": False}, + headers=user_headers, + ) + assert res.status_code == 200 + content = io.BytesIO(res.content) + dataframe = pd.read_csv(content, sep="\t") + assert list(dataframe.columns) == [ + "Capacités de transmission directes", + "Capacités de transmission indirectes", + "Hurdle costs direct (de->fr)", + "Hurdle costs indirect (fr->de)", + "Impedances", + "Loop flow", + "P.Shift Min", + "P.Shift Max", + ] + + # tests links headers after v8.2 + res = client.get( + f"/v1/studies/{study_820_id}/raw/download", + params={"path": "input/links/de/fr_parameters", "format": "tsv"}, + headers=user_headers, + ) + assert res.status_code == 200 + content = io.BytesIO(res.content) + dataframe = pd.read_csv(content, index_col=0, sep="\t") + assert list(dataframe.columns) == [ + "Hurdle costs direct (de->fr_parameters)", + "Hurdle costs indirect (fr_parameters->de)", + "Impedances", + "Loop flow", + "P.Shift Min", + "P.Shift Max", + ] + + # allocation and correlation matrices + for path in ["input/hydro/allocation", "input/hydro/correlation"]: + res = client.get( + f"/v1/studies/{study_820_id}/raw/download", params={"path": path, "format": "tsv"}, headers=user_headers + ) + assert res.status_code == 200 + content = io.BytesIO(res.content) + dataframe = pd.read_csv(content, index_col=0, sep="\t") + assert list(dataframe.index) == list(dataframe.columns) == ["de", "es", "fr", "it"] + assert all(dataframe.iloc[i, i] == 1.0 for i in range(len(dataframe))) + + # test for empty matrix + res = client.get( + f"/v1/studies/{study_id}/raw/download", + params={"path": "input/hydro/common/capacity/waterValues_de", "format": "tsv"}, + headers=user_headers, + ) + assert res.status_code == 200 + content = io.BytesIO(res.content) + dataframe = pd.read_csv(content, index_col=0, sep="\t") + assert dataframe.empty + + # modulation matrix + res = client.get( + f"/v1/studies/{study_820_id}/raw/download", + params={"path": "input/thermal/prepro/de/01_solar/modulation", "format": "tsv"}, + headers=user_headers, + ) + assert res.status_code == 200 + content = io.BytesIO(res.content) + dataframe = pd.read_csv(content, index_col=0, sep="\t") + assert dataframe.index[0] == "2018-01-01 00:00:00" + dataframe.index = range(len(dataframe)) + transposed_matrix = list(zip(*[8760 * [1.0], 8760 * [1.0], 8760 * [1.0], 8760 * [0.0]])) + expected_df = pd.DataFrame( + columns=["Marginal cost modulation", "Market bid modulation", "Capacity modulation", "Min gen modulation"], + index=range(8760), + data=transposed_matrix, + ) + assert dataframe.equals(expected_df) + + # asserts endpoint returns the right columns for output matrix + res = client.get( + f"/v1/studies/{study_id}/raw/download", + params={ + "path": "output/20201014-1422eco-hello/economy/mc-ind/00001/links/de/fr/values-hourly", + "format": "tsv", + }, + headers=user_headers, + ) + assert res.status_code == 200 + content = io.BytesIO(res.content) + dataframe = pd.read_csv(content, index_col=0, sep="\t") + # noinspection SpellCheckingInspection + assert list(dataframe.columns) == [ + "('FLOW LIN.', 'MWh', '')", + "('UCAP LIN.', 'MWh', '')", + "('LOOP FLOW', 'MWh', '')", + "('FLOW QUAD.', 'MWh', '')", + "('CONG. FEE (ALG.)', 'Euro', '')", + "('CONG. FEE (ABS.)', 'Euro', '')", + "('MARG. COST', 'Euro/MW', '')", + "('CONG. PROB +', '%', '')", + "('CONG. PROB -', '%', '')", + "('HURDLE COST', 'Euro', '')", + ] + + # test energy matrix to test the regex + res = client.get( + f"/v1/studies/{study_id}/raw/download", + params={"path": "input/hydro/prepro/de/energy", "format": "tsv"}, + headers=user_headers, + ) + assert res.status_code == 200 + content = io.BytesIO(res.content) + dataframe = pd.read_csv(content, index_col=0, sep="\t") + assert dataframe.empty + + # test the Min Gen of the 8.6 study + res = client.get( + f"/v1/studies/{study_860_id}/raw/download", + params={"path": "input/hydro/series/de/mingen", "format": "tsv"}, + headers=user_headers, + ) + assert res.status_code == 200 + content = io.BytesIO(res.content) + dataframe = pd.read_csv(content, index_col=0, sep="\t") + assert dataframe.shape == (8760, 3) + assert dataframe.columns.tolist() == ["TS-1", "TS-2", "TS-3"] + assert dataframe.index[0] == "2018-01-01 00:00:00" + # noinspection PyUnresolvedReferences + assert (dataframe.values == min_gen_df.values).all() + + # ============================= + # ERRORS + # ============================= + + fake_str = "fake_str" + + # fake study_id + res = client.get( + f"/v1/studies/{fake_str}/raw/download", + params={"path": raw_matrix_path, "format": "tsv"}, + headers=user_headers, + ) + assert res.status_code == 404 + assert res.json()["exception"] == "StudyNotFoundError" + + # fake path + res = client.get( + f"/v1/studies/{study_820_id}/raw/download", + params={"path": f"input/links/de/{fake_str}", "format": "tsv"}, + headers=user_headers, + ) + assert res.status_code == 404 + assert res.json()["exception"] == "ChildNotFoundError" + + # path that does not lead to a matrix + res = client.get( + f"/v1/studies/{study_820_id}/raw/download", + params={"path": "settings/generaldata", "format": "tsv"}, + headers=user_headers, + ) + assert res.status_code == 404 + assert res.json()["exception"] == "IncorrectPathError" + assert res.json()["description"] == "The provided path does not point to a valid matrix: 'settings/generaldata'" + + # wrong format + res = client.get( + f"/v1/studies/{study_820_id}/raw/download", + params={"path": raw_matrix_path, "format": fake_str}, + headers=user_headers, + ) + assert res.status_code == 422 + assert res.json()["exception"] == "RequestValidationError" diff --git a/tests/integration/studies_blueprint/assets/test_synthesis/raw_study.synthesis.json b/tests/integration/studies_blueprint/assets/test_synthesis/raw_study.synthesis.json index 1bf6d17f97..04ce3ddbec 100644 --- a/tests/integration/studies_blueprint/assets/test_synthesis/raw_study.synthesis.json +++ b/tests/integration/studies_blueprint/assets/test_synthesis/raw_study.synthesis.json @@ -50,7 +50,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "02_wind_on", @@ -86,7 +89,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "03_wind_off", @@ -122,7 +128,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "04_res", @@ -158,7 +167,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "05_nuclear", @@ -194,7 +206,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "06_coal", @@ -230,7 +245,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "07_gas", @@ -266,7 +284,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "08_non-res", @@ -302,7 +323,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "09_hydro_pump", @@ -338,7 +362,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 } ], "renewables": [], @@ -398,7 +425,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "02_wind_on", @@ -434,7 +464,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "03_wind_off", @@ -470,7 +503,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "04_res", @@ -506,7 +542,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "05_nuclear", @@ -542,7 +581,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "06_coal", @@ -578,7 +620,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "07_gas", @@ -614,7 +659,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "08_non-res", @@ -650,7 +698,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "09_hydro_pump", @@ -686,7 +737,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 } ], "renewables": [], @@ -746,7 +800,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "02_wind_on", @@ -782,7 +839,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "03_wind_off", @@ -818,7 +878,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "04_res", @@ -854,7 +917,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "05_nuclear", @@ -890,7 +956,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "06_coal", @@ -926,7 +995,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "07_gas", @@ -962,7 +1034,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "08_non-res", @@ -998,7 +1073,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "09_hydro_pump", @@ -1034,7 +1112,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 } ], "renewables": [], @@ -1082,7 +1163,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "02_wind_on", @@ -1118,7 +1202,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "03_wind_off", @@ -1154,7 +1241,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "04_res", @@ -1190,7 +1280,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "05_nuclear", @@ -1226,7 +1319,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "06_coal", @@ -1262,7 +1358,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "07_gas", @@ -1298,7 +1397,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "08_non-res", @@ -1334,7 +1436,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "09_hydro_pump", @@ -1370,7 +1475,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 } ], "renewables": [], diff --git a/tests/integration/studies_blueprint/assets/test_synthesis/variant_study.synthesis.json b/tests/integration/studies_blueprint/assets/test_synthesis/variant_study.synthesis.json index 4ef1428925..a77fa18a58 100644 --- a/tests/integration/studies_blueprint/assets/test_synthesis/variant_study.synthesis.json +++ b/tests/integration/studies_blueprint/assets/test_synthesis/variant_study.synthesis.json @@ -50,7 +50,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "02_wind_on", @@ -86,7 +89,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "03_wind_off", @@ -122,7 +128,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "04_res", @@ -158,7 +167,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "05_nuclear", @@ -194,7 +206,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "06_coal", @@ -230,7 +245,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "07_gas", @@ -266,7 +284,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "08_non-res", @@ -302,7 +323,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "09_hydro_pump", @@ -338,7 +362,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 } ], "renewables": [], @@ -398,7 +425,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "02_wind_on", @@ -434,7 +464,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "03_wind_off", @@ -470,7 +503,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "04_res", @@ -506,7 +542,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "05_nuclear", @@ -542,7 +581,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "06_coal", @@ -578,7 +620,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "07_gas", @@ -614,7 +659,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "08_non-res", @@ -650,7 +698,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "09_hydro_pump", @@ -686,7 +737,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 } ], "renewables": [], @@ -746,7 +800,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "02_wind_on", @@ -782,7 +839,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "03_wind_off", @@ -818,7 +878,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "04_res", @@ -854,7 +917,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "05_nuclear", @@ -890,7 +956,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "06_coal", @@ -926,7 +995,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "07_gas", @@ -962,7 +1034,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "08_non-res", @@ -998,7 +1073,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "09_hydro_pump", @@ -1034,7 +1112,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 } ], "renewables": [], @@ -1082,7 +1163,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "02_wind_on", @@ -1118,7 +1202,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "03_wind_off", @@ -1154,7 +1241,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "04_res", @@ -1190,7 +1280,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "05_nuclear", @@ -1226,7 +1319,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "06_coal", @@ -1262,7 +1358,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "07_gas", @@ -1298,7 +1397,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "08_non-res", @@ -1334,7 +1436,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 }, { "id": "09_hydro_pump", @@ -1370,7 +1475,10 @@ "op2": 0.0, "op3": 0.0, "op4": 0.0, - "op5": 0.0 + "op5": 0.0, + "costgeneration": "SetManually", + "efficiency": 100.0, + "variableomcost": 0.0 } ], "renewables": [], diff --git a/tests/integration/studies_blueprint/test_get_studies.py b/tests/integration/studies_blueprint/test_get_studies.py index 54292345f5..af8f790f20 100644 --- a/tests/integration/studies_blueprint/test_get_studies.py +++ b/tests/integration/studies_blueprint/test_get_studies.py @@ -11,6 +11,7 @@ from starlette.testclient import TestClient from antarest.core.model import PublicMode +from antarest.core.roles import RoleType from antarest.core.tasks.model import TaskStatus from tests.integration.assets import ASSETS_DIR from tests.integration.utils import wait_task_completion @@ -319,7 +320,7 @@ def test_study_listing( task = wait_task_completion(client, admin_access_token, archiving_study_task_id) assert task.status == TaskStatus.COMPLETED, task - # create a raw study version 840 to be tagged with `winter_transition` + # create a raw study version 840 to be tagged with `Winter_Transition` res = client.post( STUDIES_URL, headers={"Authorization": f"Bearer {admin_access_token}"}, @@ -330,7 +331,7 @@ def test_study_listing( res = client.put( f"{STUDIES_URL}/{tagged_raw_840_id}", headers={"Authorization": f"Bearer {admin_access_token}"}, - json={"tags": ["winter_transition"]}, + json={"tags": ["Winter_Transition"]}, ) assert res.status_code in CREATE_STATUS_CODES, res.json() res = client.get( @@ -341,7 +342,7 @@ def test_study_listing( assert res.status_code == LIST_STATUS_CODE, res.json() study_map: t.Dict[str, t.Dict[str, t.Any]] = res.json() assert len(study_map) == 1 - assert set(study_map[tagged_raw_840_id]["tags"]) == {"winter_transition"} + assert set(study_map[tagged_raw_840_id]["tags"]) == {"Winter_Transition"} # create a raw study version 850 to be tagged with `decennial` res = client.post( @@ -391,7 +392,8 @@ def test_study_listing( assert len(study_map) == 1 assert set(study_map[tagged_variant_840_id]["tags"]) == {"decennial"} - # create a variant study version 850 to be tagged with `winter_transition` + # create a variant study version 850 to be tagged with `winter_transition`. + # also test that the tag label is case-insensitive. res = client.post( f"{STUDIES_URL}/{tagged_raw_850_id}/variants", headers={"Authorization": f"Bearer {admin_access_token}"}, @@ -402,7 +404,7 @@ def test_study_listing( res = client.put( f"{STUDIES_URL}/{tagged_variant_850_id}", headers={"Authorization": f"Bearer {admin_access_token}"}, - json={"tags": ["winter_transition"]}, + json={"tags": ["winter_transition"]}, # note the tag label is in lower case ) assert res.status_code in CREATE_STATUS_CODES, res.json() res = client.get( @@ -413,7 +415,7 @@ def test_study_listing( assert res.status_code == LIST_STATUS_CODE, res.json() study_map = res.json() assert len(study_map) == 1 - assert set(study_map[tagged_variant_850_id]["tags"]) == {"winter_transition"} + assert set(study_map[tagged_variant_850_id]["tags"]) == {"Winter_Transition"} # ========================== # 2. Filtering testing @@ -452,6 +454,15 @@ def test_study_listing( study_map = res.json() assert not all_studies.intersection(study_map) assert all(map(lambda x: pm(x) in [PublicMode.READ, PublicMode.FULL], study_map.values())) + # test pagination + res = client.get( + STUDIES_URL, + headers={"Authorization": f"Bearer {john_doe_access_token}"}, + params={"pageNb": 1, "pageSize": 2}, + ) + assert res.status_code == LIST_STATUS_CODE, res.json() + page_studies = res.json() + assert len(page_studies) == max(0, min(2, len(study_map) - 2)) # test 1.b for an admin user res = client.get( @@ -461,6 +472,31 @@ def test_study_listing( assert res.status_code == LIST_STATUS_CODE, res.json() study_map = res.json() assert not all_studies.difference(study_map) + # test pagination + res = client.get( + STUDIES_URL, + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"pageNb": 1, "pageSize": 2}, + ) + assert res.status_code == LIST_STATUS_CODE, res.json() + page_studies = res.json() + assert len(page_studies) == max(0, min(len(study_map) - 2, 2)) + # test pagination concatenation + paginated_studies = {} + page_number = 0 + number_of_pages = 0 + while len(paginated_studies) < len(study_map): + res = client.get( + STUDIES_URL, + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"pageNb": page_number, "pageSize": 2}, + ) + assert res.status_code == LIST_STATUS_CODE, res.json() + paginated_studies.update(res.json()) + page_number += 1 + number_of_pages += 1 + assert paginated_studies == study_map + assert number_of_pages == len(study_map) // 2 + len(study_map) % 2 # test 1.c for a user with access to select studies res = client.get( @@ -618,6 +654,15 @@ def test_study_listing( study_map = res.json() assert not all_studies.difference(studies_version_850.union(studies_version_860)).intersection(study_map) assert not studies_version_850.union(studies_version_860).difference(study_map) + # test pagination + res = client.get( + STUDIES_URL, + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"versions": "850,860", "pageNb": 1, "pageSize": 2}, + ) + assert res.status_code == LIST_STATUS_CODE, res.json() + page_studies = res.json() + assert len(page_studies) == max(0, min(len(study_map) - 2, 2)) # tests (7) for users filtering # test 7.a to get studies for one user: James Bond @@ -670,7 +715,7 @@ def test_study_listing( res = client.get( STUDIES_URL, headers={"Authorization": f"Bearer {admin_access_token}"}, - params={"tags": "decennial"}, + params={"tags": "DECENNIAL"}, ) assert res.status_code == LIST_STATUS_CODE, res.json() study_map = res.json() @@ -801,6 +846,620 @@ def test_study_listing( values = list(study_map.values()) assert values == sorted(values, key=lambda x: x["created"], reverse=True) + def test_get_studies__access_permissions(self, client: TestClient, admin_access_token: str) -> None: + """ + Test the access permissions for the `GET /studies` endpoint. + + Args: + client: client App fixture to perform the requests + admin_access_token: fixture to get the admin access token + + Returns: + + """ + ########################## + # 1. Database initialization + ########################## + + users = {"user_1": "pass_1", "user_2": "pass_2", "user_3": "pass_3"} + users_tokens = {} + users_ids = {} + groups = {"group_1", "group_2", "group_3"} + groups_ids = {} + user_groups_mapping = {"user_1": ["group_2"], "user_2": ["group_1"], "user_3": []} + + # create users + for user, password in users.items(): + res = client.post( + "/v1/users", + headers={"Authorization": f"Bearer {admin_access_token}"}, + json={"name": user, "password": password}, + ) + res.raise_for_status() + users_ids[user] = res.json().get("id") + + # create groups + for group in groups: + res = client.post( + "/v1/groups", + headers={"Authorization": f"Bearer {admin_access_token}"}, + json={"name": group}, + ) + res.raise_for_status() + groups_ids[group] = res.json().get("id") + + # associate users to groups + for user, groups in user_groups_mapping.items(): + user_id = users_ids[user] + for group in groups: + group_id = groups_ids[group] + res = client.post( + "/v1/roles", + headers={"Authorization": f"Bearer {admin_access_token}"}, + json={"identity_id": user_id, "group_id": group_id, "type": RoleType.READER.value}, + ) + res.raise_for_status() + + # login users + for user, password in users.items(): + res = client.post( + "/v1/login", + json={"username": user, "password": password}, + ) + res.raise_for_status() + assert res.json().get("user") == users_ids[user] + users_tokens[user] = res.json().get("access_token") + + # studies creation + studies_ids_mapping = {} + + # create variant studies for user_1 and user_2 that are part of some groups + # studies that have owner and groups + for study, study_info in { + "study_1": {"owner": "user_1", "groups": ["group_1"]}, + "study_2": {"owner": "user_1", "groups": ["group_2"]}, + "study_4": {"owner": "user_2", "groups": ["group_1"]}, + "study_5": {"owner": "user_2", "groups": ["group_2"]}, + "study_7": {"owner": "user_1", "groups": ["group_1", "group_2"]}, + "study_8": {"owner": "user_2", "groups": ["group_1", "group_2"]}, + }.items(): + res = client.post( + STUDIES_URL, + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"name": f"dummy_{study[6:]}"}, + ) + assert res.status_code in CREATE_STATUS_CODES, res.json() + study_id = res.json() + res = client.post( + f"{STUDIES_URL}/{study_id}/variants", + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"name": study}, + ) + assert res.status_code in CREATE_STATUS_CODES, res.json() + study_id = res.json() + studies_ids_mapping[study] = study_id + owner_id = users_ids[study_info.get("owner")] + res = client.put( + f"{STUDIES_URL}/{study_id}/owner/{owner_id}", + headers={"Authorization": f"Bearer {admin_access_token}"}, + ) + assert res.status_code == 200, res.json() + for group in study_info.get("groups"): + group_id = groups_ids[group] + res = client.put( + f"{STUDIES_URL}/{study_id}/groups/{group_id}", + headers={"Authorization": f"Bearer {admin_access_token}"}, + ) + assert res.status_code == 200, res.json() + # studies that have owner but no groups + for study, study_info in { + "study_X10": {"owner": "user_1"}, + "study_X11": {"owner": "user_2"}, + }.items(): + res = client.post( + STUDIES_URL, + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"name": f"dummy_{study[6:]}"}, + ) + assert res.status_code in CREATE_STATUS_CODES, res.json() + study_id = res.json() + res = client.post( + f"{STUDIES_URL}/{study_id}/variants", + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"name": study}, + ) + assert res.status_code in CREATE_STATUS_CODES, res.json() + study_id = res.json() + studies_ids_mapping[study] = study_id + owner_id = users_ids[study_info.get("owner")] + res = client.put( + f"{STUDIES_URL}/{study_id}/owner/{owner_id}", + headers={"Authorization": f"Bearer {admin_access_token}"}, + ) + assert res.status_code == 200, res.json() + # studies that have groups but no owner + for study, study_info in { + "study_3": {"groups": ["group_1"]}, + "study_6": {"groups": ["group_2"]}, + "study_9": {"groups": ["group_1", "group_2"]}, + }.items(): + res = client.post( + STUDIES_URL, + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"name": f"dummy_{study[6:]}"}, + ) + assert res.status_code in CREATE_STATUS_CODES, res.json() + study_id = res.json() + res = client.post( + f"{STUDIES_URL}/{study_id}/variants", + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"name": study}, + ) + assert res.status_code in CREATE_STATUS_CODES, res.json() + study_id = res.json() + studies_ids_mapping[study] = study_id + for group in study_info.get("groups"): + group_id = groups_ids[group] + res = client.put( + f"{STUDIES_URL}/{study_id}/groups/{group_id}", + headers={"Authorization": f"Bearer {admin_access_token}"}, + ) + assert res.status_code == 200, res.json() + + # create variant studies with neither owner nor groups + for study, study_info in { + "study_X12": {"public_mode": None}, + "study_X13": {"public_mode": PublicMode.READ.value}, + "study_X14": {"public_mode": PublicMode.EDIT.value}, + "study_X15": {"public_mode": PublicMode.EXECUTE.value}, + "study_X16": {"public_mode": PublicMode.FULL.value}, + }.items(): + res = client.post( + STUDIES_URL, + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"name": f"dummy_{study[6:]}"}, + ) + assert res.status_code in CREATE_STATUS_CODES, res.json() + study_id = res.json() + res = client.post( + f"{STUDIES_URL}/{study_id}/variants", + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"name": study}, + ) + assert res.status_code in CREATE_STATUS_CODES, res.json() + study_id = res.json() + studies_ids_mapping[study] = study_id + public_mode = study_info.get("public_mode") + if public_mode: + res = client.put( + f"{STUDIES_URL}/{study_id}/public_mode/{public_mode}", + headers={"Authorization": f"Bearer {admin_access_token}"}, + ) + assert res.status_code == 200, res.json() + + # create raw studies for user_1 and user_2 that are part of some groups + # studies that have owner and groups + for study, study_info in { + "study_X17": {"owner": "user_1", "groups": ["group_1"]}, + "study_X18": {"owner": "user_1", "groups": ["group_2"]}, + "study_X20": {"owner": "user_2", "groups": ["group_1"]}, + "study_X21": {"owner": "user_2", "groups": ["group_2"]}, + "study_X23": {"owner": "user_1", "groups": ["group_1", "group_2"]}, + "study_X24": {"owner": "user_2", "groups": ["group_1", "group_2"]}, + }.items(): + res = client.post( + STUDIES_URL, + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"name": study}, + ) + assert res.status_code in CREATE_STATUS_CODES, res.json() + study_id = res.json() + studies_ids_mapping[study] = study_id + owner = users_ids[study_info.get("owner")] + res = client.put( + f"{STUDIES_URL}/{study_id}/owner/{owner}", + headers={"Authorization": f"Bearer {admin_access_token}"}, + ) + assert res.status_code == 200, res.json() + for group in study_info.get("groups"): + group_id = groups_ids[group] + res = client.put( + f"{STUDIES_URL}/{study_id}/groups/{group_id}", + headers={"Authorization": f"Bearer {admin_access_token}"}, + ) + assert res.status_code == 200, res.json() + # studies that have owner but no groups + for study, study_info in { + "study_X26": {"owner": "user_1"}, + "study_X27": {"owner": "user_2"}, + }.items(): + res = client.post( + STUDIES_URL, + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"name": study}, + ) + assert res.status_code in CREATE_STATUS_CODES, res.json() + study_id = res.json() + studies_ids_mapping[study] = study_id + owner_id = users_ids[study_info.get("owner")] + res = client.put( + f"{STUDIES_URL}/{study_id}/owner/{owner_id}", + headers={"Authorization": f"Bearer {admin_access_token}"}, + ) + assert res.status_code == 200, res.json() + # studies that have groups but no owner + for study, study_info in { + "study_X19": {"groups": ["group_1"]}, + "study_X22": {"groups": ["group_2"]}, + "study_X25": {"groups": ["group_1", "group_2"]}, + }.items(): + res = client.post( + STUDIES_URL, + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"name": study}, + ) + assert res.status_code in CREATE_STATUS_CODES, res.json() + study_id = res.json() + studies_ids_mapping[study] = study_id + for group in study_info.get("groups"): + group_id = groups_ids[group] + res = client.put( + f"{STUDIES_URL}/{study_id}/groups/{group_id}", + headers={"Authorization": f"Bearer {admin_access_token}"}, + ) + assert res.status_code == 200, res.json() + + # create raw studies with neither owner nor groups + for study, study_info in { + "study_X28": {"public_mode": None}, + "study_X29": {"public_mode": PublicMode.READ.value}, + "study_X30": {"public_mode": PublicMode.EDIT.value}, + "study_X31": {"public_mode": PublicMode.EXECUTE.value}, + "study_X32": {"public_mode": PublicMode.FULL.value}, + }.items(): + res = client.post( + STUDIES_URL, + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"name": study}, + ) + assert res.status_code in CREATE_STATUS_CODES, res.json() + study_id = res.json() + studies_ids_mapping[study] = study_id + public_mode = study_info.get("public_mode") + if public_mode: + res = client.put( + f"{STUDIES_URL}/{study_id}/public_mode/{public_mode}", + headers={"Authorization": f"Bearer {admin_access_token}"}, + ) + assert res.status_code == 200, res.json() + + # create studies for user_3 that is not part of any group + # variant studies + for study, study_info in { + "study_X33": {"groups": ["group_1"]}, + "study_X35": {"groups": []}, + }.items(): + res = client.post( + STUDIES_URL, + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"name": f"dummy_{study[6:]}"}, + ) + assert res.status_code in CREATE_STATUS_CODES, res.json() + study_id = res.json() + res = client.post( + f"{STUDIES_URL}/{study_id}/variants", + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"name": study}, + ) + assert res.status_code in CREATE_STATUS_CODES, res.json() + study_id = res.json() + studies_ids_mapping[study] = study_id + owner_id = users_ids["user_3"] + res = client.put( + f"{STUDIES_URL}/{study_id}/owner/{owner_id}", + headers={"Authorization": f"Bearer {admin_access_token}"}, + ) + assert res.status_code == 200, res.json() + for group in study_info.get("groups", []): + group_id = groups_ids[group] + res = client.put( + f"{STUDIES_URL}/{study_id}/groups/{group_id}", + headers={"Authorization": f"Bearer {admin_access_token}"}, + ) + assert res.status_code == 200, res.json() + # raw studies + for study, study_info in { + "study_X34": {"groups": ["group_2"]}, + "study_X36": {"groups": []}, + }.items(): + res = client.post( + STUDIES_URL, + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"name": study}, + ) + assert res.status_code in CREATE_STATUS_CODES, res.json() + study_id = res.json() + studies_ids_mapping[study] = study_id + owner_id = users_ids["user_3"] + res = client.put( + f"{STUDIES_URL}/{study_id}/owner/{owner_id}", + headers={"Authorization": f"Bearer {admin_access_token}"}, + ) + assert res.status_code == 200, res.json() + for group in study_info.get("groups"): + group_id = groups_ids[group] + res = client.put( + f"{STUDIES_URL}/{study_id}/groups/{group_id}", + headers={"Authorization": f"Bearer {admin_access_token}"}, + ) + assert res.status_code == 200, res.json() + + # create studies for group_3 that has no user + res = client.post( + STUDIES_URL, + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"name": "dummy_37"}, + ) + assert res.status_code in CREATE_STATUS_CODES, res.json() + study_id = res.json() + res = client.post( + f"{STUDIES_URL}/{study_id}/variants", + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"name": "study_X37"}, + ) + assert res.status_code in CREATE_STATUS_CODES, res.json() + study_id = res.json() + group_3_id = groups_ids["group_3"] + res = client.put( + f"{STUDIES_URL}/{study_id}/groups/{group_3_id}", + headers={"Authorization": f"Bearer {admin_access_token}"}, + ) + assert res.status_code == 200, res.json() + studies_ids_mapping["study_X37"] = study_id + res = client.post( + STUDIES_URL, + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"name": "study_X38"}, + ) + assert res.status_code in CREATE_STATUS_CODES, res.json() + study_id = res.json() + res = client.put( + f"{STUDIES_URL}/{study_id}/groups/{group_3_id}", + headers={"Authorization": f"Bearer {admin_access_token}"}, + ) + assert res.status_code == 200, res.json() + studies_ids_mapping["study_X38"] = study_id + + # verify the studies creation was done correctly and that admin has access to all studies + all_studies = set(studies_ids_mapping.values()) + studies_target_info = { + "study_1": { + "type": "variantstudy", + "owner": "user_1", + "groups": ["group_1"], + "public_mode": PublicMode.NONE, + }, + "study_2": { + "type": "variantstudy", + "owner": "user_1", + "groups": ["group_2"], + "public_mode": PublicMode.NONE, + }, + "study_3": {"type": "variantstudy", "owner": None, "groups": ["group_1"], "public_mode": PublicMode.NONE}, + "study_4": { + "type": "variantstudy", + "owner": "user_2", + "groups": ["group_1"], + "public_mode": PublicMode.NONE, + }, + "study_5": { + "type": "variantstudy", + "owner": "user_2", + "groups": ["group_2"], + "public_mode": PublicMode.NONE, + }, + "study_6": {"type": "variantstudy", "owner": None, "groups": ["group_2"], "public_mode": PublicMode.NONE}, + "study_7": { + "type": "variantstudy", + "owner": "user_1", + "groups": ["group_1", "group_2"], + "public_mode": PublicMode.NONE, + }, + "study_8": { + "type": "variantstudy", + "owner": "user_2", + "groups": ["group_1", "group_2"], + "public_mode": PublicMode.NONE, + }, + "study_9": { + "type": "variantstudy", + "owner": None, + "groups": ["group_1", "group_2"], + "public_mode": PublicMode.NONE, + }, + "study_X10": {"type": "variantstudy", "owner": "user_1", "groups": None, "public_mode": PublicMode.NONE}, + "study_X11": {"type": "variantstudy", "owner": "user_2", "groups": None, "public_mode": PublicMode.NONE}, + "study_X12": {"type": "variantstudy", "owner": None, "groups": None, "public_mode": PublicMode.NONE}, + "study_X13": {"type": "variantstudy", "owner": None, "groups": None, "public_mode": PublicMode.READ}, + "study_X14": {"type": "variantstudy", "owner": None, "groups": None, "public_mode": PublicMode.EDIT}, + "study_X15": {"type": "variantstudy", "owner": None, "groups": None, "public_mode": PublicMode.EXECUTE}, + "study_X16": {"type": "variantstudy", "owner": None, "groups": None, "public_mode": PublicMode.FULL}, + "study_X17": {"type": "rawstudy", "owner": "user_1", "groups": ["group_1"], "public_mode": PublicMode.NONE}, + "study_X18": {"type": "rawstudy", "owner": "user_1", "groups": ["group_2"], "public_mode": PublicMode.NONE}, + "study_X19": {"type": "rawstudy", "owner": None, "groups": ["group_1"], "public_mode": PublicMode.NONE}, + "study_X20": {"type": "rawstudy", "owner": "user_2", "groups": ["group_1"], "public_mode": PublicMode.NONE}, + "study_X21": {"type": "rawstudy", "owner": "user_2", "groups": ["group_2"], "public_mode": PublicMode.NONE}, + "study_X22": {"type": "rawstudy", "owner": None, "groups": ["group_2"], "public_mode": PublicMode.NONE}, + "study_X23": { + "type": "rawstudy", + "owner": "user_1", + "groups": ["group_1", "group_2"], + "public_mode": PublicMode.NONE, + }, + "study_X24": { + "type": "rawstudy", + "owner": "user_2", + "groups": ["group_1", "group_2"], + "public_mode": PublicMode.NONE, + }, + "study_X25": { + "type": "rawstudy", + "owner": None, + "groups": ["group_1", "group_2"], + "public_mode": PublicMode.NONE, + }, + "study_X26": {"type": "rawstudy", "owner": "user_1", "groups": None, "public_mode": PublicMode.NONE}, + "study_X27": {"type": "rawstudy", "owner": "user_2", "groups": None, "public_mode": PublicMode.NONE}, + "study_X28": {"type": "rawstudy", "owner": None, "groups": None, "public_mode": PublicMode.NONE}, + "study_X29": {"type": "rawstudy", "owner": None, "groups": None, "public_mode": PublicMode.READ}, + "study_X30": {"type": "rawstudy", "owner": None, "groups": None, "public_mode": PublicMode.EDIT}, + "study_X31": {"type": "rawstudy", "owner": None, "groups": None, "public_mode": PublicMode.EXECUTE}, + "study_X32": {"type": "rawstudy", "owner": None, "groups": None, "public_mode": PublicMode.FULL}, + "study_X33": { + "type": "variantstudy", + "owner": "user_3", + "groups": ["group_1"], + "public_mode": PublicMode.NONE, + }, + "study_X34": {"type": "rawstudy", "owner": "user_3", "groups": ["group_2"], "public_mode": PublicMode.NONE}, + "study_X35": {"type": "variantstudy", "owner": "user_3", "groups": None, "public_mode": PublicMode.NONE}, + "study_X36": {"type": "rawstudy", "owner": "user_3", "groups": None, "public_mode": PublicMode.NONE}, + "study_X37": {"type": "variantstudy", "owner": None, "groups": ["group_3"], "public_mode": PublicMode.NONE}, + "study_X38": {"type": "rawstudy", "owner": None, "groups": ["group_3"], "public_mode": PublicMode.NONE}, + } + res = client.get(STUDIES_URL, headers={"Authorization": f"Bearer {admin_access_token}"}) + assert res.status_code == LIST_STATUS_CODE, res.json() + study_map = res.json() + assert len(all_studies) == 38 + assert not all_studies.difference(study_map) + for study, study_info in studies_target_info.items(): + study_id = studies_ids_mapping[study] + study_data = study_map[study_id] + assert study_data.get("type") == study_info.get("type") + if study_data.get("owner") and study_info.get("owner"): + assert study_data["owner"]["name"] == study_info.get("owner") + assert study_data["owner"]["id"] == users_ids[study_info.get("owner")] + else: + assert not study_info.get("owner") + assert study_data["owner"]["name"] == "admin" + if study_data.get("groups"): + expected_groups = set(study_info.get("groups")) + assert all( + (group["name"] in expected_groups) and groups_ids[group["name"]] == group["id"] + for group in study_data["groups"] + ) + else: + assert not study_info.get("groups") + assert study_data["public_mode"] == study_info.get("public_mode") + + ########################## + # 2. Tests + ########################## + + # user_1 access + requests_params_expected_studies = [ + # fmt: off + ([], {"1", "2", "5", "6", "7", "8", "9", "10", "13", "14", "15", "16", "17", + "18", "21", "22", "23", "24", "25", "26", "29", "30", "31", "32", "34"}), + # fmt: on + (["1"], {"1", "7", "8", "9", "17", "23", "24", "25"}), + (["2"], {"2", "5", "6", "7", "8", "9", "18", "21", "22", "23", "24", "25", "34"}), + (["3"], set()), + (["1", "2"], {"1", "2", "5", "6", "7", "8", "9", "17", "18", "21", "22", "23", "24", "25", "34"}), + (["1", "3"], {"1", "7", "8", "9", "17", "23", "24", "25"}), + (["2", "3"], {"2", "5", "6", "7", "8", "9", "18", "21", "22", "23", "24", "25", "34"}), + ( + ["1", "2", "3"], + {"1", "2", "5", "6", "7", "8", "9", "17", "18", "21", "22", "23", "24", "25", "34"}, + ), + ] + for request_groups_numbers, expected_studies_numbers in requests_params_expected_studies: + request_groups_ids = [groups_ids[f"group_{group_number}"] for group_number in request_groups_numbers] + expected_studies = [ + studies_ids_mapping[f"study_{(study_number if int(study_number) <= 9 else 'X'+study_number)}"] + for study_number in expected_studies_numbers + ] + res = client.get( + STUDIES_URL, + headers={"Authorization": f"Bearer {users_tokens['user_1']}"}, + params={"groups": ",".join(request_groups_ids)} if request_groups_ids else {}, + ) + assert res.status_code == LIST_STATUS_CODE, res.json() + study_map = res.json() + assert not set(expected_studies).difference(set(study_map)) + assert not all_studies.difference(expected_studies).intersection(set(study_map)) + # test pagination + res = client.get( + STUDIES_URL, + headers={"Authorization": f"Bearer {users_tokens['user_1']}"}, + params={"groups": ",".join(request_groups_ids), "pageNb": 1, "pageSize": 2} + if request_groups_ids + else {"pageNb": 1, "pageSize": 2}, + ) + assert res.status_code == LIST_STATUS_CODE, res.json() + assert len(res.json()) == max(0, min(2, len(expected_studies) - 2)) + # assert list(res.json()) == expected_studies[2:4] + + # user_2 access + requests_params_expected_studies = [ + # fmt: off + ([], {"1", "3", "4", "5", "7", "8", "9", "11", "13", "14", "15", "16", "17", + "19", "20", "21", "23", "24", "25", "27", "29", "30", "31", "32", "33"}), + # fmt: on + (["1"], {"1", "3", "4", "7", "8", "9", "17", "19", "20", "23", "24", "25", "33"}), + (["2"], {"5", "7", "8", "9", "21", "23", "24", "25"}), + (["3"], set()), + (["1", "2"], {"1", "3", "4", "5", "7", "8", "9", "17", "19", "20", "21", "23", "24", "25", "33"}), + (["1", "3"], {"1", "3", "4", "7", "8", "9", "17", "19", "20", "23", "24", "25", "33"}), + (["2", "3"], {"5", "7", "8", "9", "21", "23", "24", "25"}), + ( + ["1", "2", "3"], + {"1", "3", "4", "5", "7", "8", "9", "17", "19", "20", "21", "23", "24", "25", "33"}, + ), + ] + for request_groups_numbers, expected_studies_numbers in requests_params_expected_studies: + request_groups_ids = [groups_ids[f"group_{group_number}"] for group_number in request_groups_numbers] + expected_studies = { + studies_ids_mapping[f"study_{(study_number if int(study_number) <= 9 else 'X'+study_number)}"] + for study_number in expected_studies_numbers + } + res = client.get( + STUDIES_URL, + headers={"Authorization": f"Bearer {users_tokens['user_2']}"}, + params={"groups": ",".join(request_groups_ids)} if request_groups_ids else {}, + ) + assert res.status_code == LIST_STATUS_CODE, res.json() + study_map = res.json() + assert not expected_studies.difference(set(study_map)) + assert not all_studies.difference(expected_studies).intersection(set(study_map)) + + # user_3 access + requests_params_expected_studies = [ + ([], {"13", "14", "15", "16", "29", "30", "31", "32", "33", "34", "35", "36"}), + (["1"], {"33"}), + (["2"], {"34"}), + (["3"], set()), + (["1", "2"], {"33", "34"}), + (["1", "3"], {"33"}), + (["2", "3"], {"34"}), + (["1", "2", "3"], {"33", "34"}), + ] + for request_groups_numbers, expected_studies_numbers in requests_params_expected_studies: + request_groups_ids = [groups_ids[f"group_{group_number}"] for group_number in request_groups_numbers] + expected_studies = { + studies_ids_mapping[f"study_{(study_number if int(study_number) <= 9 else 'X'+study_number)}"] + for study_number in expected_studies_numbers + } + res = client.get( + STUDIES_URL, + headers={"Authorization": f"Bearer {users_tokens['user_3']}"}, + params={"groups": ",".join(request_groups_ids)} if request_groups_ids else {}, + ) + assert res.status_code == LIST_STATUS_CODE, res.json() + study_map = res.json() + assert not expected_studies.difference(set(study_map)) + assert not all_studies.difference(expected_studies).intersection(set(study_map)) + def test_get_studies__invalid_parameters( self, client: TestClient, @@ -873,3 +1532,14 @@ def test_get_studies__invalid_parameters( assert res.status_code == INVALID_PARAMS_STATUS_CODE, res.json() description = res.json()["description"] assert re.search(r"could not be parsed to a boolean", description), f"{description=}" + + +def test_studies_counting(client: TestClient, admin_access_token: str, user_access_token: str) -> None: + # test admin and non admin user studies count requests + for access_token in [admin_access_token, user_access_token]: + res = client.get(STUDIES_URL, headers={"Authorization": f"Bearer {access_token}"}) + assert res.status_code == 200, res.json() + expected_studies_count = len(res.json()) + res = client.get(STUDIES_URL + "/count", headers={"Authorization": f"Bearer {access_token}"}) + assert res.status_code == 200, res.json() + assert res.json() == expected_studies_count diff --git a/tests/integration/studies_blueprint/test_study_matrix_index.py b/tests/integration/studies_blueprint/test_study_matrix_index.py index 69880cb357..4aeacceff4 100644 --- a/tests/integration/studies_blueprint/test_study_matrix_index.py +++ b/tests/integration/studies_blueprint/test_study_matrix_index.py @@ -33,7 +33,7 @@ def test_get_study_matrix_index( expected = { "first_week_size": 7, "level": "hourly", - "start_date": "2001-01-01 00:00:00", + "start_date": "2018-01-01 00:00:00", "steps": 8760, } assert actual == expected @@ -50,7 +50,7 @@ def test_get_study_matrix_index( expected = { "first_week_size": 7, "level": "daily", - "start_date": "2001-01-01 00:00:00", + "start_date": "2018-01-01 00:00:00", "steps": 365, } assert actual == expected @@ -67,7 +67,7 @@ def test_get_study_matrix_index( expected = { "first_week_size": 7, "level": "hourly", - "start_date": "2001-01-01 00:00:00", + "start_date": "2018-01-01 00:00:00", "steps": 8760, } assert actual == expected @@ -80,7 +80,7 @@ def test_get_study_matrix_index( actual = res.json() expected = { "first_week_size": 7, - "start_date": "2001-01-01 00:00:00", + "start_date": "2018-01-01 00:00:00", "steps": 8760, "level": "hourly", } @@ -96,5 +96,5 @@ def test_get_study_matrix_index( ) assert res.status_code == 200 actual = res.json() - expected = {"first_week_size": 7, "start_date": "2001-01-01 00:00:00", "steps": 7, "level": "daily"} + expected = {"first_week_size": 7, "start_date": "2018-01-01 00:00:00", "steps": 7, "level": "daily"} assert actual == expected diff --git a/tests/integration/studies_blueprint/test_synthesis.py b/tests/integration/studies_blueprint/test_synthesis.py index 982cc16773..1f10fa2989 100644 --- a/tests/integration/studies_blueprint/test_synthesis.py +++ b/tests/integration/studies_blueprint/test_synthesis.py @@ -108,4 +108,4 @@ def test_variant_study( ) assert res.status_code == 200, res.json() duration = time.time() - start - assert 0 <= duration <= 0.1, f"Duration is {duration} seconds" + assert 0 <= duration <= 0.2, f"Duration is {duration} seconds" diff --git a/tests/integration/studies_blueprint/test_update_tags.py b/tests/integration/studies_blueprint/test_update_tags.py new file mode 100644 index 0000000000..a65ece2f11 --- /dev/null +++ b/tests/integration/studies_blueprint/test_update_tags.py @@ -0,0 +1,95 @@ +from starlette.testclient import TestClient + + +class TestupdateStudyMetadata: + """ + Test the study tags update through the `update_study_metadata` API endpoint. + """ + + def test_update_tags( + self, + client: TestClient, + user_access_token: str, + study_id: str, + ) -> None: + """ + This test verifies that we can update the tags of a study. + It also tests the tags normalization. + """ + + # Classic usage: set some tags to a study + study_tags = ["Tag1", "Tag2"] + res = client.put( + f"/v1/studies/{study_id}", + headers={"Authorization": f"Bearer {user_access_token}"}, + json={"tags": study_tags}, + ) + assert res.status_code == 200, res.json() + actual = res.json() + assert set(actual["tags"]) == set(study_tags) + + # Update the tags with already existing tags (case-insensitive): + # - "Tag1" is preserved, but with the same case as the existing one. + # - "Tag2" is replaced by "Tag3". + study_tags = ["tag1", "Tag3"] + res = client.put( + f"/v1/studies/{study_id}", + headers={"Authorization": f"Bearer {user_access_token}"}, + json={"tags": study_tags}, + ) + assert res.status_code == 200, res.json() + actual = res.json() + assert set(actual["tags"]) != set(study_tags) # not the same case + assert set(tag.upper() for tag in actual["tags"]) == {"TAG1", "TAG3"} + + # String normalization: whitespaces are stripped and + # consecutive whitespaces are replaced by a single one. + study_tags = [" \xa0Foo \t Bar \n ", " \t Baz\xa0\xa0"] + res = client.put( + f"/v1/studies/{study_id}", + headers={"Authorization": f"Bearer {user_access_token}"}, + json={"tags": study_tags}, + ) + assert res.status_code == 200, res.json() + actual = res.json() + assert set(actual["tags"]) == {"Foo Bar", "Baz"} + + # We can have symbols in the tags + study_tags = ["Foo-Bar", ":Baz%"] + res = client.put( + f"/v1/studies/{study_id}", + headers={"Authorization": f"Bearer {user_access_token}"}, + json={"tags": study_tags}, + ) + assert res.status_code == 200, res.json() + actual = res.json() + assert set(actual["tags"]) == {"Foo-Bar", ":Baz%"} + + def test_update_tags__invalid_tags( + self, + client: TestClient, + user_access_token: str, + study_id: str, + ) -> None: + # We cannot have empty tags + study_tags = [""] + res = client.put( + f"/v1/studies/{study_id}", + headers={"Authorization": f"Bearer {user_access_token}"}, + json={"tags": study_tags}, + ) + assert res.status_code == 422, res.json() + description = res.json()["description"] + assert "Tag cannot be empty" in description + + # We cannot have tags longer than 40 characters + study_tags = ["very long tags, very long tags, very long tags"] + assert len(study_tags[0]) > 40 + res = client.put( + f"/v1/studies/{study_id}", + headers={"Authorization": f"Bearer {user_access_token}"}, + json={"tags": study_tags}, + ) + assert res.status_code == 422, res.json() + description = res.json()["description"] + assert "Tag is too long" in description diff --git a/tests/integration/study_data_blueprint/test_binding_constraints.py b/tests/integration/study_data_blueprint/test_binding_constraints.py index 93b5237f7f..fff973ae20 100644 --- a/tests/integration/study_data_blueprint/test_binding_constraints.py +++ b/tests/integration/study_data_blueprint/test_binding_constraints.py @@ -1,10 +1,15 @@ +import io +import re + +import numpy as np +import pandas as pd import pytest from starlette.testclient import TestClient -from antarest.study.business.binding_constraint_management import AreaClusterDTO, AreaLinkDTO, ConstraintTermDTO +from antarest.study.business.binding_constraint_management import ClusterTerm, ConstraintTerm, LinkTerm -class TestAreaLinkDTO: +class TestLinkTerm: @pytest.mark.parametrize( "area1, area2, expected", [ @@ -15,11 +20,11 @@ class TestAreaLinkDTO: ], ) def test_constraint_id(self, area1: str, area2: str, expected: str) -> None: - info = AreaLinkDTO(area1=area1, area2=area2) + info = LinkTerm(area1=area1, area2=area2) assert info.generate_id() == expected -class TestAreaClusterDTO: +class TestClusterTerm: @pytest.mark.parametrize( "area, cluster, expected", [ @@ -29,31 +34,31 @@ class TestAreaClusterDTO: ], ) def test_constraint_id(self, area: str, cluster: str, expected: str) -> None: - info = AreaClusterDTO(area=area, cluster=cluster) + info = ClusterTerm(area=area, cluster=cluster) assert info.generate_id() == expected -class TestConstraintTermDTO: - def test_constraint_id__link(self): - term = ConstraintTermDTO( +class TestConstraintTerm: + def test_constraint_id__link(self) -> None: + term = ConstraintTerm( id="foo", weight=3.14, offset=123, - data=AreaLinkDTO(area1="Area 1", area2="Area 2"), + data=LinkTerm(area1="Area 1", area2="Area 2"), ) assert term.generate_id() == term.data.generate_id() - def test_constraint_id__cluster(self): - term = ConstraintTermDTO( + def test_constraint_id__cluster(self) -> None: + term = ConstraintTerm( id="foo", weight=3.14, offset=123, - data=AreaClusterDTO(area="Area 1", cluster="Cluster X"), + data=ClusterTerm(area="Area 1", cluster="Cluster X"), ) assert term.generate_id() == term.data.generate_id() - def test_constraint_id__other(self): - term = ConstraintTermDTO( + def test_constraint_id__other(self) -> None: + term = ConstraintTerm( id="foo", weight=3.14, offset=123, @@ -61,20 +66,40 @@ def test_constraint_id__other(self): assert term.generate_id() == "foo" +def _upload_matrix( + client: TestClient, user_access_token: str, study_id: str, matrix_path: str, df: pd.DataFrame +) -> None: + tsv = io.BytesIO() + df.to_csv(tsv, sep="\t", index=False, header=False) + tsv.seek(0) + res = client.put( + f"/v1/studies/{study_id}/raw", + params={"path": matrix_path}, + headers={"Authorization": f"Bearer {user_access_token}"}, + files={"file": tsv}, + ) + res.raise_for_status() + + @pytest.mark.unit_test class TestBindingConstraints: """ Test the end points related to binding constraints. """ - def test_lifecycle__nominal(self, client: TestClient, user_access_token: str) -> None: + @pytest.mark.parametrize("study_type", ["raw", "variant"]) + def test_lifecycle__nominal(self, client: TestClient, user_access_token: str, study_type: str) -> None: user_headers = {"Authorization": f"Bearer {user_access_token}"} + # ============================= + # STUDY PREPARATION + # ============================= + # Create a Study res = client.post( "/v1/studies", headers=user_headers, - params={"name": "foo"}, + params={"name": "foo", "version": "860"}, ) assert res.status_code == 201, res.json() study_id = res.json() @@ -137,83 +162,129 @@ def test_lifecycle__nominal(self, client: TestClient, user_access_token: str) -> assert clusters_list[0]["name"] == "Cluster 1" assert clusters_list[0]["group"] == "Nuclear" - # Create Binding Constraints + if study_type == "variant": + # Create Variant + res = client.post( + f"/v1/studies/{study_id}/variants", + headers=user_headers, + params={"name": "Variant 1"}, + ) + assert res.status_code in {200, 201}, res.json() + study_id = res.json() + + # ============================= + # CREATION + # ============================= + + # Create Binding constraints res = client.post( - f"/v1/studies/{study_id}/bindingconstraints", - json={ - "name": "Binding Constraint 1", - "enabled": True, - "time_step": "hourly", - "operator": "less", - "coeffs": {}, - "comments": "", - }, + f"/v1/studies/{study_id}/commands", + json=[ + { + "action": "create_binding_constraint", + "args": { + "name": "binding_constraint_1", + "enabled": True, + "time_step": "hourly", + "operator": "less", + "coeffs": {}, + "comments": "", + }, + } + ], headers=user_headers, ) - assert res.status_code == 200, res.json() + assert res.status_code in {200, 201}, res.json() res = client.post( - f"/v1/studies/{study_id}/bindingconstraints", - json={ - "name": "Binding Constraint 2", - "enabled": True, - "time_step": "hourly", - "operator": "less", - "coeffs": {}, - "comments": "", - }, + f"/v1/studies/{study_id}/commands", + json=[ + { + "action": "create_binding_constraint", + "args": { + "name": "binding_constraint_2", + "enabled": True, + "time_step": "hourly", + "operator": "less", + "coeffs": {}, + "comments": "", + }, + } + ], headers=user_headers, ) - assert res.status_code == 200, res.json() + assert res.status_code in {200, 201}, res.json() - # Asserts that creating 2 binding constraints with the same name raises an Exception + # Creates a binding constraint with the new API res = client.post( f"/v1/studies/{study_id}/bindingconstraints", json={ - "name": "Binding Constraint 1", + "name": "binding_constraint_3", "enabled": True, - "time_step": "hourly", + "timeStep": "hourly", "operator": "less", - "coeffs": {}, - "comments": "", + "terms": [], + "comments": "New API", }, headers=user_headers, ) - assert res.status_code == 409, res.json() + assert res.status_code in {200, 201}, res.json() - # Get Binding Constraint list to check created binding constraints + # Get Binding Constraint list res = client.get(f"/v1/studies/{study_id}/bindingconstraints", headers=user_headers) binding_constraints_list = res.json() + assert res.status_code == 200, res.json() + assert len(binding_constraints_list) == 3 + # Group section should not exist as the study version is prior to 8.7 + assert "group" not in binding_constraints_list[0] + # check whole structure expected = [ { - "id": "binding constraint 1", - "name": "Binding Constraint 1", + "comments": "", + "terms": [], "enabled": True, - "time_step": "hourly", + "filterSynthesis": "", + "filterYearByYear": "", + "id": "binding_constraint_1", + "name": "binding_constraint_1", "operator": "less", - "constraints": None, # terms - "values": None, - "filter_year_by_year": "", - "filter_synthesis": "", + "timeStep": "hourly", + }, + { "comments": "", + "terms": [], + "enabled": True, + "filterSynthesis": "", + "filterYearByYear": "", + "id": "binding_constraint_2", + "name": "binding_constraint_2", + "operator": "less", + "timeStep": "hourly", }, { - "id": "binding constraint 2", - "name": "Binding Constraint 2", + "comments": "New API", + "terms": [], "enabled": True, - "time_step": "hourly", + "filterSynthesis": "", + "filterYearByYear": "", + "id": "binding_constraint_3", + "name": "binding_constraint_3", "operator": "less", - "constraints": None, # terms - "values": None, - "filter_year_by_year": "", - "filter_synthesis": "", - "comments": "", + "timeStep": "hourly", }, ] assert binding_constraints_list == expected bc_id = binding_constraints_list[0]["id"] + # Asserts binding constraint configuration is valid. + res = client.get(f"/v1/studies/{study_id}/constraint-groups", headers=user_headers) + assert res.status_code == 200, res.json() + + # ============================= + # CONSTRAINT TERM MANAGEMENT + # ============================= + # Add binding constraint link term res = client.post( f"/v1/studies/{study_id}/bindingconstraints/{bc_id}/term", @@ -235,7 +306,8 @@ def test_lifecycle__nominal(self, client: TestClient, user_access_token: str) -> "data": { "area": area1_id, "cluster": cluster_id, - }, # NOTE: cluster_id in term data can be uppercase, but it must be lowercase in the returned ini configuration file + }, + # NOTE: cluster_id in term data can be uppercase, but it must be lowercase in the returned ini configuration file }, headers=user_headers, ) @@ -248,18 +320,18 @@ def test_lifecycle__nominal(self, client: TestClient, user_access_token: str) -> ) assert res.status_code == 200, res.json() binding_constraint = res.json() - constraint_terms = binding_constraint["constraints"] + constraint_terms = binding_constraint["terms"] expected = [ { "data": {"area1": area1_id, "area2": area2_id}, "id": f"{area1_id}%{area2_id}", - "offset": 2.0, + "offset": 2, "weight": 1.0, }, { "data": {"area": area1_id, "cluster": cluster_id.lower()}, "id": f"{area1_id}.{cluster_id.lower()}", - "offset": 2.0, + "offset": 2, "weight": 1.0, }, ] @@ -283,12 +355,12 @@ def test_lifecycle__nominal(self, client: TestClient, user_access_token: str) -> ) assert res.status_code == 200, res.json() binding_constraint = res.json() - constraint_terms = binding_constraint["constraints"] + constraint_terms = binding_constraint["terms"] expected = [ { "data": {"area1": area1_id, "area2": area2_id}, "id": f"{area1_id}%{area2_id}", - "offset": 2.0, + "offset": 2, "weight": 1.0, }, { @@ -303,17 +375,15 @@ def test_lifecycle__nominal(self, client: TestClient, user_access_token: str) -> # Update constraint cluster term with invalid id res = client.put( f"/v1/studies/{study_id}/bindingconstraints/{bc_id}/term", - json={ - "id": f"{area1_id}.!!Invalid#cluster%%", - "weight": 4, - }, + json={"id": f"{area1_id}.!!invalid#cluster%%", "weight": 4}, headers=user_headers, ) assert res.status_code == 404, res.json() - assert res.json() == { - "description": f"{study_id}", - "exception": "ConstraintIdNotFoundError", - } + exception = res.json()["exception"] + description = res.json()["description"] + assert exception == "ConstraintTermNotFound" + assert bc_id in description + assert f"{area1_id}.!!invalid#cluster%%" in description # Update constraint cluster term with empty data res = client.put( @@ -331,256 +401,779 @@ def test_lifecycle__nominal(self, client: TestClient, user_access_token: str) -> "exception": "RequestValidationError", } - # Create Variant - res = client.post( - f"/v1/studies/{study_id}/variants", + # Remove Constraint term + res = client.delete( + f"/v1/studies/{study_id}/bindingconstraints/{bc_id}/term/{area1_id}%{area2_id}", headers=user_headers, - params={"name": "Variant 1"}, ) assert res.status_code == 200, res.json() - variant_id = res.json() - # Create Binding constraints - res = client.post( - f"/v1/studies/{variant_id}/commands", - json=[ - { - "action": "create_binding_constraint", - "args": { - "name": "binding_constraint_3", - "enabled": True, - "time_step": "hourly", - "operator": "less", - "coeffs": {}, - "comments": "", - }, - } - ], + # Check updated terms, the deleted term should no longer exist. + res = client.get( + f"/v1/studies/{study_id}/bindingconstraints/{bc_id}", headers=user_headers, ) assert res.status_code == 200, res.json() + binding_constraint = res.json() + constraint_terms = binding_constraint["terms"] + expected = [ + { + "data": {"area": area1_id, "cluster": cluster_id.lower()}, + "id": f"{area1_id}.{cluster_id.lower()}", + "offset": None, + "weight": 3.0, + }, + ] + assert constraint_terms == expected - res = client.post( - f"/v1/studies/{variant_id}/commands", - json=[ - { - "action": "create_binding_constraint", - "args": { - "name": "binding_constraint_4", - "enabled": True, - "time_step": "hourly", - "operator": "less", - "coeffs": {}, - "comments": "", - }, - } - ], + # ============================= + # GENERAL EDITION + # ============================= + + # Update element of Binding constraint + new_comment = "We made it !" + res = client.put( + f"v1/studies/{study_id}/bindingconstraints/{bc_id}", + json={"comments": new_comment}, + headers=user_headers, + ) + assert res.status_code == 200 + assert res.json()["comments"] == new_comment + + # The user change the timeStep to daily instead of hourly. + # We must check that the matrix is a daily/weekly matrix. + res = client.put( + f"/v1/studies/{study_id}/bindingconstraints/{bc_id}", + json={"timeStep": "daily"}, headers=user_headers, ) assert res.status_code == 200, res.json() + assert res.json()["timeStep"] == "daily" - # Get Binding Constraint list - res = client.get(f"/v1/studies/{variant_id}/bindingconstraints", headers=user_headers) - binding_constraints_list = res.json() + # Check that the command corresponds to a change in `time_step` + if study_type == "variant": + res = client.get(f"/v1/studies/{study_id}/commands", headers=user_headers) + commands = res.json() + args = commands[-1]["args"] + assert args["time_step"] == "daily" + assert args["values"] is not None, "We should have a matrix ID (sha256)" + + # Check that the matrix is a daily/weekly matrix + res = client.get( + f"/v1/studies/{study_id}/raw", + params={"path": f"input/bindingconstraints/{bc_id}", "depth": 1, "formatted": True}, # type: ignore + headers=user_headers, + ) assert res.status_code == 200, res.json() - assert len(binding_constraints_list) == 4 - assert binding_constraints_list[2]["id"] == "binding_constraint_3" - assert binding_constraints_list[3]["id"] == "binding_constraint_4" + dataframe = res.json() + assert len(dataframe["index"]) == 366 + assert len(dataframe["columns"]) == 3 # less, equal, greater - bc_id = binding_constraints_list[2]["id"] + # ============================= + # ERRORS + # ============================= - # Update element of Binding constraint - new_comment = "We made it !" + # Assert empty name + res = client.post( + f"/v1/studies/{study_id}/bindingconstraints", + json={ + "name": " ", + "enabled": True, + "timeStep": "hourly", + "operator": "less", + "terms": [], + "comments": "New API", + }, + headers=user_headers, + ) + assert res.status_code == 400, res.json() + assert res.json() == { + "description": "Invalid binding constraint name: .", + "exception": "InvalidConstraintName", + } + + # Assert invalid special characters + res = client.post( + f"/v1/studies/{study_id}/bindingconstraints", + json={ + "name": "%%**", + "enabled": True, + "timeStep": "hourly", + "operator": "less", + "terms": [], + "comments": "New API", + }, + headers=user_headers, + ) + assert res.status_code == 400, res.json() + assert res.json() == { + "description": "Invalid binding constraint name: %%**.", + "exception": "InvalidConstraintName", + } + + # Asserts that creating 2 binding constraints with the same name raises an Exception + res = client.post( + f"/v1/studies/{study_id}/bindingconstraints", + json={ + "name": bc_id, + "enabled": True, + "timeStep": "hourly", + "operator": "less", + "terms": [], + "comments": "", + }, + headers=user_headers, + ) + assert res.status_code == 409, res.json() + + # Creation with matrices from 2 versions: Should fail + res = client.post( + f"/v1/studies/{study_id}/bindingconstraints", + json={ + "name": "binding_constraint_x", + "enabled": True, + "timeStep": "hourly", + "operator": "less", + "terms": [], + "comments": "2 types of matrices", + "values": [[]], + "less_term_matrix": [[]], + }, + headers=user_headers, + ) + assert res.status_code == 422, res.json() + description = res.json()["description"] + assert "cannot fill 'values'" in description + assert "'less_term_matrix'" in description + assert "'greater_term_matrix'" in description + assert "'equal_term_matrix'" in description + + # Creation with wrong matrix according to version: Should fail + res = client.post( + f"/v1/studies/{study_id}/bindingconstraints", + json={ + "name": "binding_constraint_x", + "enabled": True, + "timeStep": "hourly", + "operator": "less", + "terms": [], + "comments": "Incoherent matrix with version", + "lessTermMatrix": [[]], + }, + headers=user_headers, + ) + assert res.status_code == 422, res.json() + description = res.json()["description"] + assert description == "You cannot fill a 'matrix_term' as these values refer to v8.7+ studies" + + # Wrong matrix shape + wrong_matrix = np.ones((352, 3)) + wrong_request_args = { + "name": "binding_constraint_5", + "enabled": True, + "timeStep": "daily", + "operator": "less", + "terms": [], + "comments": "Creation with matrix", + "values": wrong_matrix.tolist(), + } + res = client.post( + f"/v1/studies/{study_id}/bindingconstraints", + json=wrong_request_args, + headers=user_headers, + ) + assert res.status_code == 422, res.json() + exception = res.json()["exception"] + description = res.json()["description"] + assert exception == "RequestValidationError" + assert "'values'" in description + assert "(366, 3)" in description + + # Delete a fake binding constraint + res = client.delete(f"/v1/studies/{study_id}/bindingconstraints/fake_bc", headers=user_headers) + assert res.status_code == 404, res.json() + assert res.json()["exception"] == "BindingConstraintNotFound" + assert res.json()["description"] == "Binding constraint 'fake_bc' not found" + + # Add a group before v8.7 + grp_name = "random_grp" res = client.put( - f"v1/studies/{variant_id}/bindingconstraints/{bc_id}", - json={"key": "comments", "value": new_comment}, + f"/v1/studies/{study_id}/bindingconstraints/binding_constraint_2", + json={"group": grp_name}, headers=user_headers, ) - assert res.status_code == 200, res.json() + assert res.status_code == 422, res.json() + assert res.json()["exception"] == "InvalidFieldForVersionError" + assert ( + res.json()["description"] + == f"You cannot specify a group as your study version is older than v8.7: {grp_name}" + ) - # Get Binding Constraint - res = client.get( - f"/v1/studies/{variant_id}/bindingconstraints/{bc_id}", + # Update with a matrix from v8.7 + res = client.put( + f"/v1/studies/{study_id}/bindingconstraints/binding_constraint_2", + json={"less_term_matrix": [[]]}, headers=user_headers, ) - binding_constraint = res.json() - comments = binding_constraint["comments"] + assert res.status_code == 422, res.json() + assert res.json()["exception"] == "InvalidFieldForVersionError" + assert res.json()["description"] == "You cannot fill a 'matrix_term' as these values refer to v8.7+ studies" + + @pytest.mark.parametrize("study_type", ["raw", "variant"]) + def test_for_version_870(self, client: TestClient, admin_access_token: str, study_type: str) -> None: + admin_headers = {"Authorization": f"Bearer {admin_access_token}"} + + # ============================= + # STUDY PREPARATION + # ============================= + + res = client.post( + "/v1/studies", + headers=admin_headers, + params={"name": "foo"}, + ) + assert res.status_code == 201, res.json() + study_id = res.json() + + if study_type == "variant": + # Create Variant + res = client.post( + f"/v1/studies/{study_id}/variants", + headers=admin_headers, + params={"name": "Variant 1"}, + ) + assert res.status_code in {200, 201} + study_id = res.json() + + # Create Areas + res = client.post( + f"/v1/studies/{study_id}/areas", + headers=admin_headers, + json={ + "name": "Area 1", + "type": "AREA", + }, + ) assert res.status_code == 200, res.json() - assert comments == new_comment + area1_id = res.json()["id"] + assert area1_id == "area 1" - # Add Binding Constraint term + res = client.post( + f"/v1/studies/{study_id}/areas", + headers=admin_headers, + json={ + "name": "Area 2", + "type": "AREA", + }, + ) + assert res.status_code == 200, res.json() + area2_id = res.json()["id"] + assert area2_id == "area 2" + # Create a link between the two areas res = client.post( - f"/v1/studies/{variant_id}/bindingconstraints/{bc_id}/term", + f"/v1/studies/{study_id}/links", + headers=admin_headers, json={ - "weight": 1, - "offset": 2, - "data": {"area1": area1_id, "area2": area2_id}, + "area1": area1_id, + "area2": area2_id, }, - headers=user_headers, ) assert res.status_code == 200, res.json() - # Get Binding Constraint + # Create a cluster in area1 + res = client.post( + f"/v1/studies/{study_id}/areas/{area1_id}/clusters/thermal", + headers=admin_headers, + json={ + "name": "Cluster 1", + "group": "Nuclear", + }, + ) + assert res.status_code == 200, res.json() + cluster_id = res.json()["id"] + assert cluster_id == "Cluster 1" + + # ============================= + # CREATION + # ============================= + + # Creation of a bc without group + bc_id_wo_group = "binding_constraint_1" + args = {"enabled": True, "timeStep": "hourly", "operator": "less", "terms": [], "comments": "New API"} + res = client.post( + f"/v1/studies/{study_id}/bindingconstraints", + json={"name": bc_id_wo_group, **args}, + headers=admin_headers, + ) + assert res.status_code in {200, 201} + assert res.json()["group"] == "default" + + # Creation of bc with a group + bc_id_w_group = "binding_constraint_2" + res = client.post( + f"/v1/studies/{study_id}/bindingconstraints", + json={"name": bc_id_w_group, "group": "specific_grp", **args}, + headers=admin_headers, + ) + assert res.status_code in {200, 201} + assert res.json()["group"] == "specific_grp" + + # Creation of bc with a matrix + bc_id_w_matrix = "binding_constraint_3" + matrix_lt3 = np.ones((8784, 3)) + res = client.post( + f"/v1/studies/{study_id}/bindingconstraints", + json={"name": bc_id_w_matrix, "less_term_matrix": matrix_lt3.tolist(), **args}, + headers=admin_headers, + ) + assert res.status_code in {200, 201}, res.json() + + if study_type == "variant": + res = client.get(f"/v1/studies/{study_id}/commands", headers=admin_headers) + last_cmd_args = res.json()[-1]["args"] + less_term_matrix = last_cmd_args["less_term_matrix"] + equal_term_matrix = last_cmd_args["equal_term_matrix"] + greater_term_matrix = last_cmd_args["greater_term_matrix"] + assert greater_term_matrix == equal_term_matrix != less_term_matrix + + # Check that raw matrices are created + for term in ["lt", "gt", "eq"]: + res = client.get( + f"/v1/studies/{study_id}/raw", + params={"path": f"input/bindingconstraints/{bc_id_w_matrix}_{term}", "depth": 1, "formatted": True}, # type: ignore + headers=admin_headers, + ) + assert res.status_code == 200, res.json() + data = res.json()["data"] + if term == "lt": + assert data == matrix_lt3.tolist() + else: + assert data == np.zeros((matrix_lt3.shape[0], 1)).tolist() + + # ============================= + # CONSTRAINT TERM MANAGEMENT + # ============================= + + # Add binding constraint terms + res = client.post( + f"/v1/studies/{study_id}/bindingconstraints/{bc_id_w_group}/terms", + json=[ + {"weight": 1, "offset": 2, "data": {"area1": area1_id, "area2": area2_id}}, + {"weight": 1, "offset": 2, "data": {"area": area1_id, "cluster": cluster_id}}, + ], + headers=admin_headers, + ) + assert res.status_code == 200, res.json() + + # Attempt to add a term with missing data + res = client.post( + f"/v1/studies/{study_id}/bindingconstraints/{bc_id_w_group}/terms", + json=[{"weight": 1, "offset": 2}], + headers=admin_headers, + ) + assert res.status_code == 422, res.json() + exception = res.json()["exception"] + description = res.json()["description"] + assert exception == "InvalidConstraintTerm" + assert bc_id_w_group in description, "Error message should contain the binding constraint ID" + assert "term 'data' is missing" in description, "Error message should indicate the missing field" + + # Attempt to add a duplicate term + res = client.post( + f"/v1/studies/{study_id}/bindingconstraints/{bc_id_w_group}/terms", + json=[{"weight": 99, "offset": 0, "data": {"area1": area1_id, "area2": area2_id}}], + headers=admin_headers, + ) + assert res.status_code == 409, res.json() + exception = res.json()["exception"] + description = res.json()["description"] + assert exception == "DuplicateConstraintTerm" + assert bc_id_w_group in description, "Error message should contain the binding constraint ID" + assert f"{area1_id}%{area2_id}" in description, "Error message should contain the duplicate term ID" + + # Get binding constraints list to check added terms res = client.get( - f"/v1/studies/{variant_id}/bindingconstraints/{bc_id}", - headers=user_headers, + f"/v1/studies/{study_id}/bindingconstraints/{bc_id_w_group}", + headers=admin_headers, ) - binding_constraint = res.json() - constraints = binding_constraint["constraints"] assert res.status_code == 200, res.json() - assert binding_constraint["id"] == bc_id - assert len(constraints) == 1 - assert constraints[0]["id"] == f"{area1_id}%{area2_id}" - assert constraints[0]["weight"] == 1 - assert constraints[0]["offset"] == 2 - assert constraints[0]["data"]["area1"] == area1_id - assert constraints[0]["data"]["area2"] == area2_id - - # Update Constraint term - res = client.put( - f"/v1/studies/{variant_id}/bindingconstraints/{bc_id}/term", - json={ + binding_constraint = res.json() + constraint_terms = binding_constraint["terms"] + expected = [ + { + "data": {"area1": area1_id, "area2": area2_id}, "id": f"{area1_id}%{area2_id}", - "weight": 3, + "offset": 2, + "weight": 1.0, }, - headers=user_headers, + { + "data": {"area": area1_id, "cluster": cluster_id.lower()}, + "id": f"{area1_id}.{cluster_id.lower()}", + "offset": 2, + "weight": 1.0, + }, + ] + assert constraint_terms == expected + + # Update binding constraint terms + res = client.put( + f"/v1/studies/{study_id}/bindingconstraints/{bc_id_w_group}/terms", + json=[ + {"id": f"{area1_id}%{area2_id}", "weight": 4.4, "offset": 1}, + { + "id": f"{area1_id}.{cluster_id}", + "weight": 5.1, + "data": {"area": area1_id, "cluster": cluster_id}, + }, + ], + headers=admin_headers, ) assert res.status_code == 200, res.json() - # Get Binding Constraint + # Asserts terms were updated res = client.get( - f"/v1/studies/{variant_id}/bindingconstraints/{bc_id}", - headers=user_headers, + f"/v1/studies/{study_id}/bindingconstraints/{bc_id_w_group}", + headers=admin_headers, ) + assert res.status_code == 200, res.json() binding_constraint = res.json() - constraints = binding_constraint["constraints"] + constraint_terms = binding_constraint["terms"] + expected = [ + { + "data": {"area1": area1_id, "area2": area2_id}, + "id": f"{area1_id}%{area2_id}", + "offset": 1, + "weight": 4.4, + }, + { + "data": {"area": area1_id, "cluster": cluster_id.lower()}, + "id": f"{area1_id}.{cluster_id.lower()}", + "offset": None, + "weight": 5.1, + }, + ] + assert constraint_terms == expected + + # ============================= + # UPDATE + # ============================= + + # Add a group + grp_name = "random_grp" + res = client.put( + f"/v1/studies/{study_id}/bindingconstraints/{bc_id_w_matrix}", + json={"group": grp_name}, + headers=admin_headers, + ) assert res.status_code == 200, res.json() - assert binding_constraint["id"] == bc_id - assert len(constraints) == 1 - assert constraints[0]["id"] == f"{area1_id}%{area2_id}" - assert constraints[0]["weight"] == 3 - assert constraints[0]["offset"] is None - assert constraints[0]["data"]["area1"] == area1_id - assert constraints[0]["data"]["area2"] == area2_id + assert res.json()["group"] == grp_name - # Remove Constraint term - res = client.delete( - f"/v1/studies/{variant_id}/bindingconstraints/{bc_id}/term/{area1_id}%{area2_id}", - headers=user_headers, + # Update matrix_term + res = client.put( + f"/v1/studies/{study_id}/bindingconstraints/{bc_id_w_matrix}", + json={"greater_term_matrix": matrix_lt3.tolist()}, + headers=admin_headers, ) assert res.status_code == 200, res.json() - # Get Binding Constraint res = client.get( - f"/v1/studies/{variant_id}/bindingconstraints/{bc_id}", - headers=user_headers, + f"/v1/studies/{study_id}/raw", + params={"path": f"input/bindingconstraints/{bc_id_w_matrix}_gt"}, + headers=admin_headers, ) - binding_constraint = res.json() - constraints = binding_constraint["constraints"] assert res.status_code == 200, res.json() - assert constraints is None + assert res.json()["data"] == matrix_lt3.tolist() - # Creates a binding constraint with the new API - res = client.post( - f"/v1/studies/{variant_id}/bindingconstraints", - json={ - "name": "binding_constraint_5", - "enabled": True, - "time_step": "hourly", - "operator": "less", - "coeffs": {}, - "comments": "New API", - }, - headers=user_headers, + # The user changed the timeStep to daily instead of hourly. + # We must check that the matrices have been updated. + res = client.put( + f"/v1/studies/{study_id}/bindingconstraints/{bc_id_w_matrix}", + json={"timeStep": "daily"}, + headers=admin_headers, ) assert res.status_code == 200, res.json() - # Asserts that creating 2 binding constraints with the same name raises an Exception + if study_type == "variant": + # Check the last command is a change on `time_step` field only + res = client.get(f"/v1/studies/{study_id}/commands", headers=admin_headers) + commands = res.json() + command_args = commands[-1]["args"] + assert command_args["time_step"] == "daily" + assert "values" not in command_args + assert ( + command_args["less_term_matrix"] + == command_args["greater_term_matrix"] + == command_args["equal_term_matrix"] + is not None + ) + + # Check that the matrices are daily/weekly matrices + expected_matrix = np.zeros((366, 1)) + for term_alias in ["lt", "gt", "eq"]: + res = client.get( + f"/v1/studies/{study_id}/raw", + params={ + "path": f"input/bindingconstraints/{bc_id_w_matrix}_{term_alias}", + "depth": 1, + "formatted": True, + }, # type: ignore + headers=admin_headers, + ) + assert res.status_code == 200, res.json() + assert res.json()["data"] == expected_matrix.tolist() + + # ============================= + # DELETE + # ============================= + + # Delete a binding constraint + res = client.delete(f"/v1/studies/{study_id}/bindingconstraints/{bc_id_w_group}", headers=admin_headers) + assert res.status_code == 200, res.json() + + # Asserts that the deletion worked + res = client.get(f"/v1/studies/{study_id}/bindingconstraints", headers=admin_headers) + assert len(res.json()) == 2 + + # ============================= + # ERRORS + # ============================= + + # Creation with wrong matrix according to version res = client.post( - f"/v1/studies/{variant_id}/bindingconstraints", + f"/v1/studies/{study_id}/bindingconstraints", json={ - "name": "binding_constraint_5", + "name": "binding_constraint_700", "enabled": True, - "time_step": "hourly", + "timeStep": "hourly", "operator": "less", - "coeffs": {}, + "terms": [], "comments": "New API", + "values": [[]], }, - headers=user_headers, + headers=admin_headers, ) - assert res.status_code == 409, res.json() - assert res.json() == { - "description": "A binding constraint with the same name already exists: binding_constraint_5.", - "exception": "DuplicateConstraintName", - } + assert res.status_code == 422, res.json() + assert res.json()["description"] == "You cannot fill 'values' as it refers to the matrix before v8.7" - # Assert empty name + # Update with old matrices + res = client.put( + f"/v1/studies/{study_id}/bindingconstraints/{bc_id_w_matrix}", + json={"values": [[]]}, + headers=admin_headers, + ) + assert res.status_code == 422, res.json() + assert res.json()["exception"] == "InvalidFieldForVersionError" + assert res.json()["description"] == "You cannot fill 'values' as it refers to the matrix before v8.7" + + # Creation with 2 matrices with different columns size + bc_id_with_wrong_matrix = "binding_constraint_with_wrong_matrix" + matrix_lt3 = np.ones((8784, 3)) + matrix_gt2 = np.ones((8784, 2)) # Wrong number of columns res = client.post( - f"/v1/studies/{variant_id}/bindingconstraints", + f"/v1/studies/{study_id}/bindingconstraints", json={ - "name": " ", - "enabled": True, - "time_step": "hourly", - "operator": "less", - "coeffs": {}, - "comments": "New API", + "name": bc_id_with_wrong_matrix, + "less_term_matrix": matrix_lt3.tolist(), + "greater_term_matrix": matrix_gt2.tolist(), + **args, }, - headers=user_headers, + headers=admin_headers, ) - assert res.status_code == 400, res.json() - assert res.json() == { - "description": "Invalid binding constraint name: .", - "exception": "InvalidConstraintName", - } + assert res.status_code == 422, res.json() + exception = res.json()["exception"] + description = res.json()["description"] + assert exception == "RequestValidationError" + assert "'less_term_matrix'" in description + assert "'greater_term_matrix'" in description + assert "(8784, 3)" in description + assert "(8784, 2)" in description - # Assert invalid special characters + # + # Creation of 1 BC + # Update raw with wrong columns size -> OK but validation should fail + # + + matrix_lt3 = np.ones((8784, 3)) res = client.post( - f"/v1/studies/{variant_id}/bindingconstraints", + f"/v1/studies/{study_id}/bindingconstraints", json={ - "name": "%%**", - "enabled": True, - "time_step": "hourly", - "operator": "less", - "coeffs": {}, - "comments": "New API", + "name": "First BC", + "less_term_matrix": matrix_lt3.tolist(), + "group": "Group 1", + **args, }, - headers=user_headers, + headers=admin_headers, ) - assert res.status_code == 400, res.json() - assert res.json() == { - "description": "Invalid binding constraint name: %%**.", - "exception": "InvalidConstraintName", - } + assert res.status_code in {200, 201}, res.json() + first_bc_id = res.json()["id"] - # Asserts that 5 binding constraints have been created - res = client.get(f"/v1/studies/{variant_id}/bindingconstraints", headers=user_headers) - assert res.status_code == 200, res.json() - assert len(res.json()) == 5 + generator = np.random.default_rng(11) + random_matrix = pd.DataFrame(generator.integers(0, 10, size=(4, 1))) + _upload_matrix( + client, + admin_access_token, + study_id, + f"input/bindingconstraints/{first_bc_id}_gt", + random_matrix, + ) - # The user change the time_step to daily instead of hourly. - # We must check that the matrix is a daily/weekly matrix. + # Validation should fail + res = client.get( + f"/v1/studies/{study_id}/constraint-groups/Group 1/validate", + headers=admin_headers, + ) + assert res.status_code == 422 + obj = res.json() + assert obj["exception"] == "WrongMatrixHeightError" + assert obj["description"] == "The binding constraint 'First BC' should have 8784 rows, currently: 4" + + # So, we correct the shape of the matrix res = client.put( - f"/v1/studies/{variant_id}/bindingconstraints/{bc_id}", - json={"key": "time_step", "value": "daily"}, - headers=user_headers, + f"/v1/studies/{study_id}/bindingconstraints/{first_bc_id}", + json={"greater_term_matrix": matrix_lt3.tolist()}, + headers=admin_headers, ) - assert res.status_code == 200, res.json() + assert res.status_code in {200, 201}, res.json() - # Check the last command is a change time_step - res = client.get(f"/v1/studies/{variant_id}/commands", headers=user_headers) - commands = res.json() - args = commands[-1]["args"] - assert args["time_step"] == "daily" - assert args["values"] is not None, "We should have a matrix ID (sha256)" + # + # Creation of another BC inside the same group with different columns size + # "Second BC": 4 cols, "Group 1" -> OK, but should fail in group validation + # - # Check that the matrix is a daily/weekly matrix + # Asserts everything is ok. res = client.get( - f"/v1/studies/{variant_id}/raw", - params={"path": f"input/bindingconstraints/{bc_id}", "depth": 1, "formatted": True}, - headers=user_headers, + f"/v1/studies/{study_id}/constraint-groups/Group 1/validate", + headers=admin_headers, ) assert res.status_code == 200, res.json() - dataframe = res.json() - assert len(dataframe["index"]) == 366 - assert len(dataframe["columns"]) == 3 # less, equal, greater + + matrix_gt4 = np.ones((8784, 4)) # Wrong number of columns + res = client.post( + f"/v1/studies/{study_id}/bindingconstraints", + json={ + "name": "Second BC", + "greater_term_matrix": matrix_gt4.tolist(), + "group": "group 1", # Same group, but different case + **args, + }, + headers=admin_headers, + ) + assert res.status_code in {200, 201}, res.json() + second_bc_id = res.json()["id"] + + # validate the BC group "Group 1" + res = client.get(f"/v1/studies/{study_id}/constraint-groups/Group 1/validate", headers=admin_headers) + assert res.status_code == 422, res.json() + assert res.json()["exception"] == "MatrixWidthMismatchError" + description = res.json()["description"] + assert re.search(r"the most common width in the group is 3", description, flags=re.IGNORECASE) + assert re.search(r"'second bc_gt' has 4 columns", description, flags=re.IGNORECASE) + + # So, we correct the shape of the matrix of the Second BC + res = client.put( + f"/v1/studies/{study_id}/bindingconstraints/{second_bc_id}", + json={"greater_term_matrix": matrix_lt3.tolist()}, + headers=admin_headers, + ) + assert res.status_code in {200, 201}, res.json() + + # + # Updating the group of a bc creates different columns size inside the same group + # first_bc: 3 cols, "Group 1" -> OK + # third_bd: 4 cols, "Group 2" -> OK + # third_bd group changes to group1 -> Fails validation + # + + matrix_lt4 = np.ones((8784, 4)) + res = client.post( + f"/v1/studies/{study_id}/bindingconstraints", + json={ + "name": "Third BC", + "less_term_matrix": matrix_lt4.tolist(), + "group": "Group 2", + **args, + }, + headers=admin_headers, + ) + assert res.status_code in {200, 201}, res.json() + third_bd_id = res.json()["id"] + + res = client.put( + f"v1/studies/{study_id}/bindingconstraints/{third_bd_id}", + json={"group": "Group 1"}, + headers=admin_headers, + ) + # This should succeed but cause the validation endpoint to fail. + assert res.status_code in {200, 201}, res.json() + + # validate the BC group "Group 1" + res = client.get(f"/v1/studies/{study_id}/constraint-groups/Group 1/validate", headers=admin_headers) + assert res.status_code == 422, res.json() + assert res.json()["exception"] == "MatrixWidthMismatchError" + description = res.json()["description"] + assert re.search(r"the most common width in the group is 3", description, flags=re.IGNORECASE) + assert re.search(r"'third bc_lt' has 4 columns", description, flags=re.IGNORECASE) + + # So, we correct the shape of the matrix of the Second BC + res = client.put( + f"/v1/studies/{study_id}/bindingconstraints/{third_bd_id}", + json={"greater_term_matrix": matrix_lt3.tolist()}, + headers=admin_headers, + ) + assert res.status_code in {200, 201}, res.json() + + # + # Update causes different matrices size inside the same bc + # second_bc: 1st matrix has 4 cols and others 1 -> OK + # second_bc: 1st matrix has 4 cols and 2nd matrix has 3 cols -> Fails validation + # + + res = client.put( + f"v1/studies/{study_id}/bindingconstraints/{second_bc_id}", + json={"group": "Group 2"}, + headers=admin_headers, + ) + assert res.status_code in {200, 201}, res.json() + + # validate the "Group 2": for the moment the BC is valid + res = client.get(f"/v1/studies/{study_id}/constraint-groups/Group 2/validate", headers=admin_headers) + assert res.status_code in {200, 201}, res.json() + + res = client.put( + f"v1/studies/{study_id}/bindingconstraints/{second_bc_id}", + json={"greater_term_matrix": matrix_gt4.tolist()}, + headers=admin_headers, + ) + # This should succeed but cause the validation endpoint to fail. + assert res.status_code in {200, 201}, res.json() + + # Collect all the binding constraints groups + res = client.get(f"/v1/studies/{study_id}/constraint-groups", headers=admin_headers) + assert res.status_code in {200, 201}, res.json() + groups = res.json() + assert set(groups) == {"default", "random_grp", "Group 1", "Group 2"} + assert groups["Group 2"] == [ + { + "comments": "New API", + "terms": [], + "enabled": True, + "filterSynthesis": "", + "filterYearByYear": "", + "group": "Group 2", + "id": "second bc", + "name": "Second BC", + "operator": "less", + "timeStep": "hourly", + } + ] + + # Validate all binding constraints groups + res = client.get(f"/v1/studies/{study_id}/constraint-groups/validate-all", headers=admin_headers) + assert res.status_code == 422, res.json() + exception = res.json()["exception"] + description = res.json()["description"] + assert exception == "MatrixWidthMismatchError" + assert re.search(r"'Group 1':", description, flags=re.IGNORECASE) + assert re.search(r"the most common width in the group is 3", description, flags=re.IGNORECASE) + assert re.search(r"'third bc_lt' has 4 columns", description, flags=re.IGNORECASE) diff --git a/tests/integration/study_data_blueprint/test_renewable.py b/tests/integration/study_data_blueprint/test_renewable.py index 8447c0430f..8a9d575d97 100644 --- a/tests/integration/study_data_blueprint/test_renewable.py +++ b/tests/integration/study_data_blueprint/test_renewable.py @@ -23,6 +23,7 @@ * delete a cluster (or several clusters) * validate the consistency of the matrices (and properties) """ + import json import re import typing as t @@ -475,8 +476,8 @@ def test_lifecycle( ) assert res.status_code == 404 obj = res.json() - assert obj["description"] == f"Cluster: '{unknown_id}' not found" - assert obj["exception"] == "ClusterNotFound" + assert f"'{unknown_id}' not found" in obj["description"] + assert obj["exception"] == "RenewableClusterNotFound" # Cannot duplicate with an existing id res = client.post( @@ -488,7 +489,7 @@ def test_lifecycle( obj = res.json() description = obj["description"] assert other_cluster_name.upper() in description - assert obj["exception"] == "ClusterAlreadyExists" + assert obj["exception"] == "DuplicateRenewableCluster" @pytest.fixture(name="base_study_id") def base_study_id_fixture(self, request: t.Any, client: TestClient, user_access_token: str) -> str: diff --git a/tests/integration/study_data_blueprint/test_st_storage.py b/tests/integration/study_data_blueprint/test_st_storage.py index 161e6417b8..b8aa0de878 100644 --- a/tests/integration/study_data_blueprint/test_st_storage.py +++ b/tests/integration/study_data_blueprint/test_st_storage.py @@ -8,14 +8,22 @@ from starlette.testclient import TestClient from antarest.core.tasks.model import TaskStatus -from antarest.study.business.areas.st_storage_management import STStorageOutput +from antarest.study.business.areas.st_storage_management import create_storage_output from antarest.study.storage.rawstudy.model.filesystem.config.model import transform_name_to_id -from antarest.study.storage.rawstudy.model.filesystem.config.st_storage import STStorageConfig +from antarest.study.storage.rawstudy.model.filesystem.config.st_storage import create_st_storage_config from tests.integration.utils import wait_task_completion -DEFAULT_CONFIG = json.loads(STStorageConfig(id="dummy", name="dummy").json(by_alias=True, exclude={"id", "name"})) +_ST_STORAGE_860_CONFIG = create_st_storage_config(860, name="dummy") +_ST_STORAGE_880_CONFIG = create_st_storage_config(880, name="dummy") -DEFAULT_PROPERTIES = json.loads(STStorageOutput(name="dummy").json(by_alias=True, exclude={"id", "name"})) +_ST_STORAGE_OUTPUT_860 = create_storage_output(860, cluster_id="dummy", config={"name": "dummy"}) +_ST_STORAGE_OUTPUT_880 = create_storage_output(880, cluster_id="dummy", config={"name": "dummy"}) + +DEFAULT_CONFIG_860 = json.loads(_ST_STORAGE_860_CONFIG.json(by_alias=True, exclude={"id", "name"})) +DEFAULT_CONFIG_880 = json.loads(_ST_STORAGE_880_CONFIG.json(by_alias=True, exclude={"id", "name"})) + +DEFAULT_OUTPUT_860 = json.loads(_ST_STORAGE_OUTPUT_860.json(by_alias=True, exclude={"id", "name"})) +DEFAULT_OUTPUT_880 = json.loads(_ST_STORAGE_OUTPUT_880.json(by_alias=True, exclude={"id", "name"})) # noinspection SpellCheckingInspection @@ -30,8 +38,21 @@ class TestSTStorage: """ @pytest.mark.parametrize("study_type", ["raw", "variant"]) + @pytest.mark.parametrize( + "study_version, default_output", + [ + pytest.param(860, DEFAULT_OUTPUT_860, id="860"), + pytest.param(880, DEFAULT_OUTPUT_880, id="880"), + ], + ) def test_lifecycle__nominal( - self, client: TestClient, user_access_token: str, study_id: str, study_type: str + self, + client: TestClient, + user_access_token: str, + study_id: str, + study_type: str, + study_version: int, + default_output: t.Dict[str, t.Any], ) -> None: """ The purpose of this integration test is to test the endpoints @@ -62,11 +83,11 @@ def test_lifecycle__nominal( # ============================= user_headers = {"Authorization": f"Bearer {user_access_token}"} - # Upgrade study to version 860 + # Upgrade study to version 860 or above res = client.put( f"/v1/studies/{study_id}/upgrade", headers=user_headers, - params={"target_version": 860}, + params={"target_version": study_version}, ) res.raise_for_status() task_id = res.json() @@ -99,10 +120,9 @@ def test_lifecycle__nominal( area_id = transform_name_to_id("FR") siemens_battery = "Siemens Battery" - # Un attempt to create a short-term storage without name + # An attempt to create a short-term storage without name # should raise a validation error (other properties are optional). - # Un attempt to create a short-term storage with an empty name - # or an invalid name should also raise a validation error. + # The same goes for empty or invalid names attempts = [{}, {"name": ""}, {"name": "!??"}] for attempt in attempts: res = client.post( @@ -113,9 +133,9 @@ def test_lifecycle__nominal( assert res.status_code == 422, res.json() assert res.json()["exception"] in {"ValidationError", "RequestValidationError"}, res.json() - # We can create a short-term storage with the following properties: + # We can create a short-term storage with the following properties. + # Unfilled properties will be set to their default values. siemens_properties = { - **DEFAULT_PROPERTIES, "name": siemens_battery, "group": "Battery", "injectionNominalCapacity": 1450, @@ -130,8 +150,8 @@ def test_lifecycle__nominal( assert res.status_code == 200, res.json() siemens_battery_id = res.json()["id"] assert siemens_battery_id == transform_name_to_id(siemens_battery) - siemens_config = {**siemens_properties, "id": siemens_battery_id} - assert res.json() == siemens_config + siemens_output = {**default_output, **siemens_properties, "id": siemens_battery_id} + assert res.json() == siemens_output # reading the properties of a short-term storage res = client.get( @@ -139,7 +159,7 @@ def test_lifecycle__nominal( headers=user_headers, ) assert res.status_code == 200, res.json() - assert res.json() == siemens_config + assert res.json() == siemens_output # ============================= # SHORT-TERM STORAGE MATRICES @@ -188,7 +208,7 @@ def test_lifecycle__nominal( headers=user_headers, ) assert res.status_code == 200, res.json() - assert res.json() == [siemens_config] + assert res.json() == [siemens_output] # updating properties res = client.patch( @@ -200,19 +220,19 @@ def test_lifecycle__nominal( }, ) assert res.status_code == 200, res.json() - siemens_config = { - **siemens_config, + siemens_output = { + **siemens_output, "name": "New Siemens Battery", "reservoirCapacity": 2500, } - assert res.json() == siemens_config + assert res.json() == siemens_output res = client.get( f"/v1/studies/{study_id}/areas/{area_id}/storages/{siemens_battery_id}", headers=user_headers, ) assert res.status_code == 200, res.json() - assert res.json() == siemens_config + assert res.json() == siemens_output # =========================== # SHORT-TERM STORAGE UPDATE @@ -227,13 +247,13 @@ def test_lifecycle__nominal( "reservoirCapacity": 0, }, ) - siemens_config = { - **siemens_config, + siemens_output = { + **siemens_output, "initialLevel": 0.59, "reservoirCapacity": 0, } assert res.status_code == 200, res.json() - assert res.json() == siemens_config + assert res.json() == siemens_output # An attempt to update the `efficiency` property with an invalid value # should raise a validation error. @@ -253,7 +273,7 @@ def test_lifecycle__nominal( headers=user_headers, ) assert res.status_code == 200, res.json() - assert res.json() == siemens_config + assert res.json() == siemens_output # ============================= # SHORT-TERM STORAGE DUPLICATION @@ -267,11 +287,11 @@ def test_lifecycle__nominal( ) assert res.status_code in {200, 201}, res.json() # asserts the config is the same - duplicated_config = dict(siemens_config) - duplicated_config["name"] = new_name # type: ignore + duplicated_output = dict(siemens_output) + duplicated_output["name"] = new_name duplicated_id = transform_name_to_id(new_name) - duplicated_config["id"] = duplicated_id # type: ignore - assert res.json() == duplicated_config + duplicated_output["id"] = duplicated_id + assert res.json() == duplicated_output # asserts the matrix has also been duplicated res = client.get( @@ -351,16 +371,16 @@ def test_lifecycle__nominal( headers=user_headers, ) assert res.status_code == 200, res.json() - siemens_config = {**DEFAULT_PROPERTIES, **siemens_properties, "id": siemens_battery_id} - grand_maison_config = {**DEFAULT_PROPERTIES, **grand_maison_properties, "id": grand_maison_id} - assert res.json() == [duplicated_config, siemens_config, grand_maison_config] + siemens_output = {**default_output, **siemens_properties, "id": siemens_battery_id} + grand_maison_output = {**default_output, **grand_maison_properties, "id": grand_maison_id} + assert res.json() == [duplicated_output, siemens_output, grand_maison_output] # We can delete the three short-term storages at once. res = client.request( "DELETE", f"/v1/studies/{study_id}/areas/{area_id}/storages", headers=user_headers, - json=[grand_maison_id, duplicated_config["id"]], + json=[grand_maison_id, duplicated_output["id"]], ) assert res.status_code == 204, res.json() assert res.text in {"", "null"} # Old FastAPI versions return 'null'. @@ -477,8 +497,10 @@ def test_lifecycle__nominal( ) assert res.status_code == 404 obj = res.json() - assert obj["description"] == f"Short-term storage '{bad_storage_id}' not found in area '{area_id}'" - assert obj["exception"] == "STStorageNotFoundError" + description = obj["description"] + assert bad_storage_id in description + assert re.search(r"'bad_storage'", description, flags=re.IGNORECASE) + assert re.search(r"not found", description, flags=re.IGNORECASE) # Check PATCH with the wrong `study_id` res = client.patch( @@ -500,8 +522,8 @@ def test_lifecycle__nominal( ) assert res.status_code == 404, res.json() obj = res.json() - assert obj["description"] == f"Fields of storage '{unknown_id}' not found" - assert obj["exception"] == "STStorageFieldsNotFoundError" + assert f"'{unknown_id}' not found" in obj["description"] + assert obj["exception"] == "STStorageNotFound" # Cannot duplicate with an existing id res = client.post( @@ -513,10 +535,39 @@ def test_lifecycle__nominal( obj = res.json() description = obj["description"] assert siemens_battery.lower() in description - assert obj["exception"] == "ClusterAlreadyExists" + assert obj["exception"] == "DuplicateSTStorage" + + # Cannot specify the field 'enabled' before v8.8 + properties = {"enabled": False, "name": "fake_name", "group": "Battery"} + res = client.post( + f"/v1/studies/{study_id}/areas/{area_id}/storages", + headers=user_headers, + json=properties, + ) + if study_version < 880: + assert res.status_code == 422 + assert res.json()["exception"] == "ValidationError" + else: + assert res.status_code == 200 + assert res.json()["enabled"] is False @pytest.mark.parametrize("study_type", ["raw", "variant"]) - def test__default_values(self, client: TestClient, user_access_token: str, study_type: str) -> None: + @pytest.mark.parametrize( + "study_version, default_config, default_output", + [ + pytest.param(860, DEFAULT_CONFIG_860, DEFAULT_OUTPUT_860, id="860"), + pytest.param(880, DEFAULT_CONFIG_880, DEFAULT_OUTPUT_880, id="880"), + ], + ) + def test__default_values( + self, + client: TestClient, + user_access_token: str, + study_type: str, + study_version: int, + default_config: t.Dict[str, t.Any], + default_output: t.Dict[str, t.Any], + ) -> None: """ The purpose of this integration test is to test the default values of the properties of a short-term storage. @@ -530,7 +581,7 @@ def test__default_values(self, client: TestClient, user_access_token: str, study res = client.post( "/v1/studies", headers=user_headers, - params={"name": "MyStudy", "version": 860}, + params={"name": "MyStudy", "version": study_version}, ) assert res.status_code in {200, 201}, res.json() study_id = res.json() @@ -563,8 +614,8 @@ def test__default_values(self, client: TestClient, user_access_token: str, study ) assert res.status_code == 200, res.json() tesla_battery_id = res.json()["id"] - tesla_config = {**DEFAULT_PROPERTIES, "id": tesla_battery_id, "name": tesla_battery, "group": "Battery"} - assert res.json() == tesla_config + tesla_output = {**default_output, "id": tesla_battery_id, "name": tesla_battery, "group": "Battery"} + assert res.json() == tesla_output # Use the Debug mode to make sure that the initialLevel and initialLevelOptim properties # are properly set in the configuration file. @@ -575,7 +626,7 @@ def test__default_values(self, client: TestClient, user_access_token: str, study ) assert res.status_code == 200, res.json() actual = res.json() - expected = {**DEFAULT_CONFIG, "name": tesla_battery, "group": "Battery"} + expected = {**default_config, "name": tesla_battery, "group": "Battery"} assert actual == expected # We want to make sure that the default properties are applied to a study variant. @@ -614,7 +665,7 @@ def test__default_values(self, client: TestClient, user_access_token: str, study "action": "create_st_storage", "args": { "area_id": "fr", - "parameters": {**DEFAULT_CONFIG, "name": siemens_battery, "group": "Battery"}, + "parameters": {**default_config, "name": siemens_battery, "group": "Battery"}, "pmax_injection": ANY, "pmax_withdrawal": ANY, "lower_rule_curve": ANY, @@ -698,7 +749,7 @@ def test__default_values(self, client: TestClient, user_access_token: str, study assert res.status_code == 200, res.json() actual = res.json() expected = { - **DEFAULT_CONFIG, + **default_config, "name": siemens_battery, "group": "Battery", "injectionnominalcapacity": 1600, diff --git a/tests/integration/study_data_blueprint/test_table_mode.py b/tests/integration/study_data_blueprint/test_table_mode.py new file mode 100644 index 0000000000..45ca2cc961 --- /dev/null +++ b/tests/integration/study_data_blueprint/test_table_mode.py @@ -0,0 +1,917 @@ +import typing as t + +import pytest +from starlette.testclient import TestClient + +from antarest.core.tasks.model import TaskStatus +from tests.integration.utils import wait_task_completion + +# noinspection SpellCheckingInspection +POLLUTANTS_860 = ("nh3", "nmvoc", "nox", "op1", "op2", "op3", "op4", "op5", "pm10", "pm25", "pm5", "so2") + + +# noinspection SpellCheckingInspection +@pytest.mark.unit_test +class TestTableMode: + """ + Test the end points related to the table mode. + + Those tests use the "examples/studies/STA-mini.zip" Study, + which contains the following areas: ["de", "es", "fr", "it"]. + """ + + @pytest.mark.parametrize("study_version", [0, 810, 830, 860, 870, 880]) + def test_lifecycle__nominal( + self, client: TestClient, user_access_token: str, study_id: str, study_version: int + ) -> None: + user_headers = {"Authorization": f"Bearer {user_access_token}"} + + # In order to test the table mode for renewable clusters and short-term storage, + # it is required that the study is either in version 8.1 for renewable energies + # or in version 8.6 for short-term storage and that the renewable clusters are enabled + # in the study configuration. + + # Upgrade the study to the desired version + if study_version: + res = client.put( + f"/v1/studies/{study_id}/upgrade", + headers={"Authorization": f"Bearer {user_access_token}"}, + params={"target_version": study_version}, + ) + assert res.status_code == 200, res.json() + + task_id = res.json() + task = wait_task_completion(client, user_access_token, task_id) + assert task.status == TaskStatus.COMPLETED, task + + # Table Mode - Area + # ================= + + # Get the schema of the areas table + res = client.get( + "/v1/table-schema/areas", + headers=user_headers, + ) + assert res.status_code == 200, res.json() + actual = res.json() + assert set(actual["properties"]) == { + # Optimization - Nodal optimization + "nonDispatchablePower", + "dispatchableHydroPower", + "otherDispatchablePower", + "averageUnsuppliedEnergyCost", + "spreadUnsuppliedEnergyCost", + "averageSpilledEnergyCost", + "spreadSpilledEnergyCost", + # Optimization - Filtering + "filterSynthesis", + "filterYearByYear", + # Adequacy patch + "adequacyPatchMode", + } + + _de_values = { + "averageUnsuppliedEnergyCost": 3456, + "dispatchableHydroPower": False, + "filterSynthesis": "daily, monthly", # not changed + "filterYearByYear": "annual, weekly", + } + _es_values = {"spreadSpilledEnergyCost": None} # not changed + + if study_version >= 830: + _es_values["adequacyPatchMode"] = "inside" + + res = client.put( + f"/v1/studies/{study_id}/table-mode/areas", + headers=user_headers, + json={ + "de": _de_values, + "es": _es_values, + }, + ) + assert res.status_code == 200, res.json() + expected_areas: t.Dict[str, t.Dict[str, t.Any]] + expected_areas = { + "de": { + "averageSpilledEnergyCost": 0, + "averageUnsuppliedEnergyCost": 3456, + "dispatchableHydroPower": False, + "filterSynthesis": "daily, monthly", + "filterYearByYear": "weekly, annual", + "nonDispatchablePower": True, + "otherDispatchablePower": True, + "spreadSpilledEnergyCost": 0, + "spreadUnsuppliedEnergyCost": 0, + }, + "es": { + "averageSpilledEnergyCost": 0, + "averageUnsuppliedEnergyCost": 3000, + "dispatchableHydroPower": True, + "filterSynthesis": "daily, monthly", + "filterYearByYear": "hourly, weekly, annual", + "nonDispatchablePower": True, + "otherDispatchablePower": True, + "spreadSpilledEnergyCost": 0, + "spreadUnsuppliedEnergyCost": 0, + }, + "fr": { + "averageSpilledEnergyCost": 0, + "averageUnsuppliedEnergyCost": 3000, + "dispatchableHydroPower": True, + "filterSynthesis": "", + "filterYearByYear": "hourly", + "nonDispatchablePower": True, + "otherDispatchablePower": True, + "spreadSpilledEnergyCost": 0, + "spreadUnsuppliedEnergyCost": 0, + }, + "it": { + "averageSpilledEnergyCost": 0, + "averageUnsuppliedEnergyCost": 3000, + "dispatchableHydroPower": True, + "filterSynthesis": "", + "filterYearByYear": "hourly", + "nonDispatchablePower": True, + "otherDispatchablePower": True, + "spreadSpilledEnergyCost": 0, + "spreadUnsuppliedEnergyCost": 0, + }, + } + + if study_version >= 830: + expected_areas["de"]["adequacyPatchMode"] = "outside" + expected_areas["es"]["adequacyPatchMode"] = "inside" + expected_areas["fr"]["adequacyPatchMode"] = "outside" + expected_areas["it"]["adequacyPatchMode"] = "outside" + + actual = res.json() + assert actual == expected_areas + + res = client.get(f"/v1/studies/{study_id}/table-mode/areas", headers=user_headers) + assert res.status_code == 200, res.json() + actual = res.json() + assert actual == expected_areas + + # Table Mode - Links + # ================== + + # Get the schema of the links table + res = client.get( + "/v1/table-schema/links", + headers=user_headers, + ) + assert res.status_code == 200, res.json() + actual = res.json() + assert set(actual["properties"]) == { + "colorRgb", + "comments", + "hurdlesCost", + "loopFlow", + "usePhaseShifter", + "transmissionCapacities", + "assetType", + "linkStyle", + "linkWidth", + "displayComments", + "filterSynthesis", + "filterYearByYear", + } + + res = client.put( + f"/v1/studies/{study_id}/table-mode/links", + headers=user_headers, + json={ + "de / fr": { + "colorRgb": "#FFA500", + "displayComments": False, + "filterSynthesis": "hourly, daily, weekly, annual", + "filterYearByYear": "hourly, daily, monthly, annual", + "hurdlesCost": True, + "linkStyle": "plain", + "linkWidth": 2, + "loopFlow": False, + "transmissionCapacities": "ignore", + }, + "es / fr": { + "colorRgb": "#FF6347", + "displayComments": True, + "filterSynthesis": "hourly, daily, weekly, monthly, annual, annual", # duplicate is ignored + "filterYearByYear": "hourly, daily, weekly, annual", + "hurdlesCost": True, + "linkStyle": "plain", + "linkWidth": 1, + "loopFlow": False, + "transmissionCapacities": "enabled", + "usePhaseShifter": True, + }, + "fr / it": { + "comments": "Link from France to Italie", + "assetType": "DC", # case-insensitive + }, + }, + ) + assert res.status_code == 200, res.json() + expected_links = { + "de / fr": { + "assetType": "ac", + "colorRgb": "#FFA500", + "comments": "", + "displayComments": False, + "filterSynthesis": "hourly, daily, weekly, annual", + "filterYearByYear": "hourly, daily, monthly, annual", + "hurdlesCost": True, + "linkStyle": "plain", + "linkWidth": 2, + "loopFlow": False, + "transmissionCapacities": "ignore", + "usePhaseShifter": False, + }, + "es / fr": { + "assetType": "ac", + "colorRgb": "#FF6347", + "comments": "", + "displayComments": True, + "filterSynthesis": "hourly, daily, weekly, monthly, annual", + "filterYearByYear": "hourly, daily, weekly, annual", + "hurdlesCost": True, + "linkStyle": "plain", + "linkWidth": 1, + "loopFlow": False, + "transmissionCapacities": "enabled", + "usePhaseShifter": True, + }, + "fr / it": { + "assetType": "dc", + "colorRgb": "#707070", + "comments": "Link from France to Italie", + "displayComments": True, + "filterSynthesis": "", + "filterYearByYear": "hourly", + "hurdlesCost": True, + "linkStyle": "plain", + "linkWidth": 1, + "loopFlow": False, + "transmissionCapacities": "enabled", + "usePhaseShifter": False, + }, + } + actual = res.json() + assert actual == expected_links + + res = client.get(f"/v1/studies/{study_id}/table-mode/links", headers=user_headers) + assert res.status_code == 200, res.json() + actual = res.json() + assert actual == expected_links + + # Table Mode - Thermal Clusters + # ============================= + + # Get the schema of the thermals table + res = client.get( + "/v1/table-schema/thermals", + headers=user_headers, + ) + assert res.status_code == 200, res.json() + actual = res.json() + assert set(actual["properties"]) == { + # read-only fields + "id", + "name", + # Thermals fields + "group", + "enabled", + "unitCount", + "nominalCapacity", + "genTs", + "minStablePower", + "minUpTime", + "minDownTime", + "mustRun", + "spinning", + "volatilityForced", + "volatilityPlanned", + "lawForced", + "lawPlanned", + "marginalCost", + "spreadCost", + "fixedCost", + "startupCost", + "marketBidCost", + # pollutants - since v8.6 (except for "co2") + "co2", + "nh3", + "so2", + "nox", + "pm25", + "pm5", + "pm10", + "nmvoc", + "op1", + "op2", + "op3", + "op4", + "op5", + # since v8.7 + "costGeneration", + "efficiency", + "variableOMCost", + } + + _solar_values = {"group": "Other 2", "nominalCapacity": 500000, "unitCount": 17} + _wind_on_values = {"group": "Nuclear", "nominalCapacity": 314159, "unitCount": 15, "co2": 123} + if study_version >= 860: + _solar_values["so2"] = 8.25 + if study_version >= 870: + _solar_values.update({"costGeneration": "useCostTimeseries", "efficiency": 87, "variableOMCost": -12.5}) + + res = client.put( + f"/v1/studies/{study_id}/table-mode/thermals", + headers=user_headers, + json={ + "de / 01_solar": _solar_values, + "de / 02_wind_on": _wind_on_values, + }, + ) + assert res.status_code == 200, res.json() + expected_thermals = { + "de / 01_solar": { + # "id": "01_solar", + # "name": "01_solar", + "co2": 0, + "costGeneration": None, + "efficiency": None, + "enabled": True, + "fixedCost": 0, + "genTs": "use global", + "group": "Other 2", + "lawForced": "uniform", + "lawPlanned": "uniform", + "marginalCost": 10, + "marketBidCost": 10, + "minDownTime": 1, + "minStablePower": 0, + "minUpTime": 1, + "mustRun": False, + "nominalCapacity": 500000, + "spinning": 0, + "spreadCost": 0, + "startupCost": 0, + "unitCount": 17, + "variableOMCost": None, + "volatilityForced": 0, + "volatilityPlanned": 0, + }, + "de / 02_wind_on": { + # "id": "02_wind_on", + # "name": "02_wind_on", + "co2": 123, + "costGeneration": None, + "efficiency": None, + "enabled": True, + "fixedCost": 0, + "genTs": "use global", + "group": "Nuclear", + "lawForced": "uniform", + "lawPlanned": "uniform", + "marginalCost": 20, + "marketBidCost": 20, + "minDownTime": 1, + "minStablePower": 0, + "minUpTime": 1, + "mustRun": False, + "nominalCapacity": 314159, + "spinning": 0, + "spreadCost": 0, + "startupCost": 0, + "unitCount": 15, + "variableOMCost": None, + "volatilityForced": 0, + "volatilityPlanned": 0, + }, + } + + if study_version >= 860: + _values = dict.fromkeys(POLLUTANTS_860, 0) + expected_thermals["de / 02_wind_on"].update(_values) + expected_thermals["de / 01_solar"].update(_values, **{"so2": 8.25}) + else: + _values = dict.fromkeys(POLLUTANTS_860) + expected_thermals["de / 02_wind_on"].update(_values) + expected_thermals["de / 01_solar"].update(_values) + + if study_version >= 870: + _values = {"costGeneration": "SetManually", "efficiency": 100, "variableOMCost": 0} + expected_thermals["de / 02_wind_on"].update(_values) + _values = {"costGeneration": "useCostTimeseries", "efficiency": 87, "variableOMCost": -12.5} + expected_thermals["de / 01_solar"].update(_values) + + assert res.json()["de / 01_solar"] == expected_thermals["de / 01_solar"] + assert res.json()["de / 02_wind_on"] == expected_thermals["de / 02_wind_on"] + + res = client.get( + f"/v1/studies/{study_id}/table-mode/thermals", + headers=user_headers, + params={"columns": ",".join(["group", "unitCount", "nominalCapacity", "so2"])}, + ) + assert res.status_code == 200, res.json() + expected: t.Dict[str, t.Dict[str, t.Any]] + expected = { + "de / 01_solar": {"group": "Other 2", "nominalCapacity": 500000, "unitCount": 17}, + "de / 02_wind_on": {"group": "Nuclear", "nominalCapacity": 314159, "unitCount": 15}, + "de / 03_wind_off": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "de / 04_res": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "de / 05_nuclear": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "de / 06_coal": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "de / 07_gas": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "de / 08_non-res": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "de / 09_hydro_pump": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "es / 01_solar": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "es / 02_wind_on": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "es / 03_wind_off": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "es / 04_res": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "es / 05_nuclear": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "es / 06_coal": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "es / 07_gas": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "es / 08_non-res": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "es / 09_hydro_pump": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "fr / 01_solar": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "fr / 02_wind_on": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "fr / 03_wind_off": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "fr / 04_res": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "fr / 05_nuclear": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "fr / 06_coal": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "fr / 07_gas": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "fr / 08_non-res": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "fr / 09_hydro_pump": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "it / 01_solar": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "it / 02_wind_on": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "it / 03_wind_off": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "it / 04_res": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "it / 05_nuclear": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "it / 06_coal": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "it / 07_gas": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "it / 08_non-res": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + "it / 09_hydro_pump": {"group": "Other 1", "nominalCapacity": 1000000, "unitCount": 1}, + } + if study_version >= 860: + for key in expected: + expected[key]["so2"] = 0 + expected["de / 01_solar"]["so2"] = 8.25 + + actual = res.json() + assert actual == expected + + # Table Mode - Renewable Clusters + # =============================== + + # only concerns studies after v8.1 + if study_version >= 810: + # Parameter 'renewable-generation-modelling' must be set to 'clusters' instead of 'aggregated'. + # The `enr_modelling` value must be set to "clusters" instead of "aggregated" + args = { + "target": "settings/generaldata/other preferences", + "data": {"renewable-generation-modelling": "clusters"}, + } + res = client.post( + f"/v1/studies/{study_id}/commands", + headers={"Authorization": f"Bearer {user_access_token}"}, + json=[{"action": "update_config", "args": args}], + ) + assert res.status_code == 200, res.json() + + # Prepare data for renewable clusters tests + generators_by_country = { + "fr": { + "La Rochelle": { + "name": "La Rochelle", + "group": "solar pv", + "nominalCapacity": 2.1, + "unitCount": 1, + "tsInterpretation": "production-factor", + }, + "Oleron": { + "name": "Oleron", + "group": "wind offshore", + "nominalCapacity": 15, + "unitCount": 70, + "tsInterpretation": "production-factor", + }, + "Dieppe": { + "name": "Dieppe", + "group": "wind offshore", + "nominalCapacity": 8, + "unitCount": 62, + "tsInterpretation": "power-generation", + }, + }, + "it": { + "Sicile": { + "name": "Sicile", + "group": "solar pv", + "nominalCapacity": 1.8, + "unitCount": 1, + "tsInterpretation": "production-factor", + }, + "Sardaigne": { + "name": "Sardaigne", + "group": "wind offshore", + "nominalCapacity": 12, + "unitCount": 86, + "tsInterpretation": "power-generation", + }, + "Pouilles": { + "name": "Pouilles", + "enabled": False, + "group": "wind offshore", + "nominalCapacity": 11, + "unitCount": 40, + "tsInterpretation": "power-generation", + }, + }, + } + + for area_id, generators in generators_by_country.items(): + for generator_id, generator in generators.items(): + res = client.post( + f"/v1/studies/{study_id}/areas/{area_id}/clusters/renewable", + headers=user_headers, + json=generator, + ) + res.raise_for_status() + + # Get the schema of the renewables table + res = client.get( + "/v1/table-schema/renewables", + headers=user_headers, + ) + assert res.status_code == 200, res.json() + actual = res.json() + assert set(actual["properties"]) == { + # read-only fields + "id", + "name", + # Renewables fields + "group", + "tsInterpretation", + "enabled", + "unitCount", + "nominalCapacity", + } + + # Update some generators using the table mode + res = client.put( + f"/v1/studies/{study_id}/table-mode/renewables", + headers=user_headers, + json={ + "fr / Dieppe": {"enabled": False}, + "fr / La Rochelle": {"enabled": True, "nominalCapacity": 3.1, "unitCount": 2}, + "it / Pouilles": {"group": "Wind Onshore"}, + }, + ) + assert res.status_code == 200, res.json() + + res = client.get( + f"/v1/studies/{study_id}/table-mode/renewables", + headers=user_headers, + params={"columns": ",".join(["group", "enabled", "unitCount", "nominalCapacity"])}, + ) + assert res.status_code == 200, res.json() + expected = { + "fr / Dieppe": {"enabled": False, "group": "Wind Offshore", "nominalCapacity": 8, "unitCount": 62}, + "fr / La Rochelle": {"enabled": True, "group": "Solar PV", "nominalCapacity": 3.1, "unitCount": 2}, + "fr / Oleron": {"enabled": True, "group": "Wind Offshore", "nominalCapacity": 15, "unitCount": 70}, + "it / Pouilles": {"enabled": False, "group": "Wind Onshore", "nominalCapacity": 11, "unitCount": 40}, + "it / Sardaigne": {"enabled": True, "group": "Wind Offshore", "nominalCapacity": 12, "unitCount": 86}, + "it / Sicile": {"enabled": True, "group": "Solar PV", "nominalCapacity": 1.8, "unitCount": 1}, + } + actual = res.json() + assert actual == expected + + # Table Mode - Short Term Storage + # =============================== + + # only concerns studies after v8.6 + if study_version >= 860: + # Get the schema of the short-term storages table + res = client.get( + "/v1/table-schema/st-storages", + headers=user_headers, + ) + assert res.status_code == 200, res.json() + actual = res.json() + assert set(actual["properties"]) == { + # read-only fields + "id", + "name", + # Short-term storage fields + "enabled", # since v8.8 + "group", + "injectionNominalCapacity", + "withdrawalNominalCapacity", + "reservoirCapacity", + "efficiency", + "initialLevel", + "initialLevelOptim", + } + + # Prepare data for short-term storage tests + storage_by_country = { + "fr": { + "siemens": { + "name": "Siemens", + "group": "battery", + "injectionNominalCapacity": 1500, + "withdrawalNominalCapacity": 1500, + "reservoirCapacity": 1500, + "initialLevel": 0.5, + "initialLevelOptim": False, + }, + "tesla": { + "name": "Tesla", + "group": "battery", + "injectionNominalCapacity": 1200, + "withdrawalNominalCapacity": 1200, + "reservoirCapacity": 1200, + "initialLevelOptim": True, + }, + }, + "it": { + "storage3": { + "name": "storage3", + "group": "psp_open", + "injectionNominalCapacity": 1234, + "withdrawalNominalCapacity": 1020, + "reservoirCapacity": 1357, + "initialLevel": 1, + "initialLevelOptim": False, + }, + "storage4": { + "name": "storage4", + "group": "psp_open", + "injectionNominalCapacity": 567, + "withdrawalNominalCapacity": 456, + "reservoirCapacity": 500, + "initialLevelOptim": True, + }, + }, + } + for area_id, storages in storage_by_country.items(): + for storage_id, storage in storages.items(): + res = client.post( + f"/v1/studies/{study_id}/areas/{area_id}/storages", + headers=user_headers, + json=storage, + ) + res.raise_for_status() + + # Update some generators using the table mode + _fr_siemes_values = {"injectionNominalCapacity": 1550, "withdrawalNominalCapacity": 1550} + _fr_tesla_values = {"efficiency": 0.75, "initialLevel": 0.89, "initialLevelOptim": False} + _it_storage3_values = {"group": "Pondage"} + if study_version >= 880: + _it_storage3_values["enabled"] = False + + res = client.put( + f"/v1/studies/{study_id}/table-mode/st-storages", + headers=user_headers, + json={ + "fr / siemens": _fr_siemes_values, + "fr / tesla": _fr_tesla_values, + "it / storage3": _it_storage3_values, + }, + ) + assert res.status_code == 200, res.json() + actual = res.json() + expected = { + "fr / siemens": { + # "id": "siemens", + # "name": "Siemens", + "efficiency": 1, + "enabled": None, + "group": "Battery", + "initialLevel": 0.5, + "initialLevelOptim": False, + "injectionNominalCapacity": 1550, + "reservoirCapacity": 1500, + "withdrawalNominalCapacity": 1550, + }, + "fr / tesla": { + # "id": "tesla", + # "name": "Tesla", + "efficiency": 0.75, + "enabled": None, + "group": "Battery", + "initialLevel": 0.89, + "initialLevelOptim": False, + "injectionNominalCapacity": 1200, + "reservoirCapacity": 1200, + "withdrawalNominalCapacity": 1200, + }, + "it / storage3": { + # "id": "storage3", + # "name": "storage3", + "efficiency": 1, + "enabled": None, + "group": "Pondage", + "initialLevel": 1, + "initialLevelOptim": False, + "injectionNominalCapacity": 1234, + "reservoirCapacity": 1357, + "withdrawalNominalCapacity": 1020, + }, + "it / storage4": { + # "id": "storage4", + # "name": "storage4", + "efficiency": 1, + "enabled": None, + "group": "PSP_open", + "initialLevel": 0.5, + "initialLevelOptim": True, + "injectionNominalCapacity": 567, + "reservoirCapacity": 500, + "withdrawalNominalCapacity": 456, + }, + } + + if study_version >= 880: + for key in expected: + expected[key]["enabled"] = True + expected["it / storage3"]["enabled"] = False + + assert actual == expected + + res = client.get( + f"/v1/studies/{study_id}/table-mode/st-storages", + headers=user_headers, + params={ + "columns": ",".join( + [ + "group", + "injectionNominalCapacity", + "withdrawalNominalCapacity", + "reservoirCapacity", + "unknowColumn", # should be ignored + ] + ), + }, + ) + assert res.status_code == 200, res.json() + expected = { + "fr / siemens": { + "group": "Battery", + "injectionNominalCapacity": 1550, + "reservoirCapacity": 1500, + "withdrawalNominalCapacity": 1550, + }, + "fr / tesla": { + "group": "Battery", + "injectionNominalCapacity": 1200, + "reservoirCapacity": 1200, + "withdrawalNominalCapacity": 1200, + }, + "it / storage3": { + "group": "Pondage", + "injectionNominalCapacity": 1234, + "reservoirCapacity": 1357, + "withdrawalNominalCapacity": 1020, + }, + "it / storage4": { + "group": "PSP_open", + "injectionNominalCapacity": 567, + "reservoirCapacity": 500, + "withdrawalNominalCapacity": 456, + }, + } + actual = res.json() + assert actual == expected + + # Table Mode - Binding Constraints + # ================================ + + # Prepare data for binding constraints tests + # Create a cluster in fr + fr_id = "fr" + res = client.post( + f"/v1/studies/{study_id}/areas/{fr_id}/clusters/thermal", + headers=user_headers, + json={ + "name": "Cluster 1", + "group": "Nuclear", + }, + ) + assert res.status_code == 200, res.json() + cluster_id = res.json()["id"] + assert cluster_id == "Cluster 1" + + # Create Binding Constraints + res = client.post( + f"/v1/studies/{study_id}/bindingconstraints", + json={ + "name": "Binding Constraint 1", + "enabled": True, + "time_step": "hourly", + "operator": "less", + }, + headers=user_headers, + ) + assert res.status_code == 200, res.json() + + res = client.post( + f"/v1/studies/{study_id}/bindingconstraints", + json={ + "name": "Binding Constraint 2", + "enabled": False, + "time_step": "daily", + "operator": "greater", + "comments": "This is a binding constraint", + "filter_synthesis": "hourly, daily, weekly", + }, + headers=user_headers, + ) + assert res.status_code == 200, res.json() + + # Get the schema of the binding constraints table + res = client.get( + "/v1/table-schema/binding-constraints", + headers=user_headers, + ) + assert res.status_code == 200, res.json() + actual = res.json() + assert set(actual["properties"]) == { + # read-only fields + "id", + "name", + # Binding Constraints fields + "group", # since v8.7 + "enabled", + "timeStep", + "operator", + "comments", + "filterSynthesis", + "filterYearByYear", + # Binding Constraints - Terms + "terms", + } + + # Update some binding constraints using the table mode + _bc1_values = {"comments": "Hello World!", "enabled": True} + _bc2_values = {"filterSynthesis": "hourly", "filterYearByYear": "hourly", "operator": "both"} + if study_version >= 870: + _bc2_values["group"] = "My BC Group" + + res = client.put( + f"/v1/studies/{study_id}/table-mode/binding-constraints", + headers=user_headers, + json={ + "binding constraint 1": _bc1_values, + "binding constraint 2": _bc2_values, + }, + ) + assert res.status_code == 200, res.json() + actual = res.json() + expected_binding = { + "binding constraint 1": { + "comments": "Hello World!", + "enabled": True, + "operator": "less", + "timeStep": "hourly", + }, + "binding constraint 2": { + "comments": "This is a binding constraint", + "enabled": False, + "operator": "both", + "timeStep": "daily", + }, + } + if study_version >= 830: + expected_binding["binding constraint 1"]["filterSynthesis"] = "" + expected_binding["binding constraint 1"]["filterYearByYear"] = "" + expected_binding["binding constraint 2"]["filterSynthesis"] = "hourly" + expected_binding["binding constraint 2"]["filterYearByYear"] = "hourly" + + if study_version >= 870: + expected_binding["binding constraint 1"]["group"] = "default" + expected_binding["binding constraint 2"]["group"] = "My BC Group" + + assert actual == expected_binding + + res = client.get( + f"/v1/studies/{study_id}/table-mode/binding-constraints", + headers=user_headers, + params={"columns": ""}, + ) + assert res.status_code == 200, res.json() + expected = expected_binding + actual = res.json() + assert actual == expected + + +def test_table_type_aliases(client: TestClient, user_access_token: str) -> None: + """ + Ensure that we can use the old table type aliases to get the schema of the tables. + """ + user_headers = {"Authorization": f"Bearer {user_access_token}"} + # do not use `pytest.mark.parametrize`, because it is too slow + for table_type in ["area", "link", "cluster", "renewable", "binding constraint"]: + res = client.get(f"/v1/table-schema/{table_type}", headers=user_headers) + assert res.status_code == 200, f"Failed to get schema for {table_type}: {res.json()}" diff --git a/tests/integration/study_data_blueprint/test_thermal.py b/tests/integration/study_data_blueprint/test_thermal.py index 9fc7388642..e3f62eca1e 100644 --- a/tests/integration/study_data_blueprint/test_thermal.py +++ b/tests/integration/study_data_blueprint/test_thermal.py @@ -27,24 +27,24 @@ * delete a cluster (or several clusters) * validate the consistency of the matrices (and properties) """ +import io import json import re import typing as t import numpy as np +import pandas as pd import pytest from starlette.testclient import TestClient from antarest.core.utils.string import to_camel_case from antarest.study.storage.rawstudy.model.filesystem.config.model import transform_name_to_id -from antarest.study.storage.rawstudy.model.filesystem.config.thermal import Thermal860Properties, ThermalProperties +from antarest.study.storage.rawstudy.model.filesystem.config.thermal import ThermalProperties +from tests.integration.utils import wait_task_completion DEFAULT_PROPERTIES = json.loads(ThermalProperties(name="Dummy").json()) DEFAULT_PROPERTIES = {to_camel_case(k): v for k, v in DEFAULT_PROPERTIES.items() if k != "name"} -DEFAULT_860_PROPERTIES = json.loads(Thermal860Properties(name="Dummy").json()) -DEFAULT_860_PROPERTIES = {to_camel_case(k): v for k, v in DEFAULT_860_PROPERTIES.items() if k != "name"} - # noinspection SpellCheckingInspection EXISTING_CLUSTERS = [ { @@ -63,19 +63,7 @@ "minUpTime": 1, "mustRun": False, "name": "01_solar", - "nh3": None, - "nmvoc": None, "nominalCapacity": 1000000.0, - "nox": None, - "op1": None, - "op2": None, - "op3": None, - "op4": None, - "op5": None, - "pm10": None, - "pm25": None, - "pm5": None, - "so2": None, "spinning": 0.0, "spreadCost": 0.0, "startupCost": 0.0, @@ -99,19 +87,7 @@ "minUpTime": 1, "mustRun": False, "name": "02_wind_on", - "nh3": None, - "nmvoc": None, "nominalCapacity": 1000000.0, - "nox": None, - "op1": None, - "op2": None, - "op3": None, - "op4": None, - "op5": None, - "pm10": None, - "pm25": None, - "pm5": None, - "so2": None, "spinning": 0.0, "spreadCost": 0.0, "startupCost": 0.0, @@ -135,19 +111,7 @@ "minUpTime": 1, "mustRun": False, "name": "03_wind_off", - "nh3": None, - "nmvoc": None, "nominalCapacity": 1000000.0, - "nox": None, - "op1": None, - "op2": None, - "op3": None, - "op4": None, - "op5": None, - "pm10": None, - "pm25": None, - "pm5": None, - "so2": None, "spinning": 0.0, "spreadCost": 0.0, "startupCost": 0.0, @@ -171,19 +135,7 @@ "minUpTime": 1, "mustRun": False, "name": "04_res", - "nh3": None, - "nmvoc": None, "nominalCapacity": 1000000.0, - "nox": None, - "op1": None, - "op2": None, - "op3": None, - "op4": None, - "op5": None, - "pm10": None, - "pm25": None, - "pm5": None, - "so2": None, "spinning": 0.0, "spreadCost": 0.0, "startupCost": 0.0, @@ -207,19 +159,7 @@ "minUpTime": 1, "mustRun": False, "name": "05_nuclear", - "nh3": None, - "nmvoc": None, "nominalCapacity": 1000000.0, - "nox": None, - "op1": None, - "op2": None, - "op3": None, - "op4": None, - "op5": None, - "pm10": None, - "pm25": None, - "pm5": None, - "so2": None, "spinning": 0.0, "spreadCost": 0.0, "startupCost": 0.0, @@ -243,19 +183,7 @@ "minUpTime": 1, "mustRun": False, "name": "06_coal", - "nh3": None, - "nmvoc": None, "nominalCapacity": 1000000.0, - "nox": None, - "op1": None, - "op2": None, - "op3": None, - "op4": None, - "op5": None, - "pm10": None, - "pm25": None, - "pm5": None, - "so2": None, "spinning": 0.0, "spreadCost": 0.0, "startupCost": 0.0, @@ -279,19 +207,7 @@ "minUpTime": 1, "mustRun": False, "name": "07_gas", - "nh3": None, - "nmvoc": None, "nominalCapacity": 1000000.0, - "nox": None, - "op1": None, - "op2": None, - "op3": None, - "op4": None, - "op5": None, - "pm10": None, - "pm25": None, - "pm5": None, - "so2": None, "spinning": 0.0, "spreadCost": 0.0, "startupCost": 0.0, @@ -315,19 +231,7 @@ "minUpTime": 1, "mustRun": False, "name": "08_non-res", - "nh3": None, - "nmvoc": None, "nominalCapacity": 1000000.0, - "nox": None, - "op1": None, - "op2": None, - "op3": None, - "op4": None, - "op5": None, - "pm10": None, - "pm25": None, - "pm5": None, - "so2": None, "spinning": 0.0, "spreadCost": 0.0, "startupCost": 0.0, @@ -351,19 +255,7 @@ "minUpTime": 1, "mustRun": False, "name": "09_hydro_pump", - "nh3": None, - "nmvoc": None, "nominalCapacity": 1000000.0, - "nox": None, - "op1": None, - "op2": None, - "op3": None, - "op4": None, - "op5": None, - "pm10": None, - "pm25": None, - "pm5": None, - "so2": None, "spinning": 0.0, "spreadCost": 0.0, "startupCost": 0.0, @@ -374,18 +266,67 @@ ] +def _upload_matrix( + client: TestClient, user_access_token: str, study_id: str, matrix_path: str, df: pd.DataFrame +) -> None: + tsv = io.BytesIO() + df.to_csv(tsv, sep="\t", index=False, header=False) + tsv.seek(0) + res = client.put( + f"/v1/studies/{study_id}/raw", + params={"path": matrix_path}, + headers={"Authorization": f"Bearer {user_access_token}"}, + files={"file": tsv}, + ) + res.raise_for_status() + + @pytest.mark.unit_test class TestThermal: + @pytest.mark.parametrize( + "version", [pytest.param(0, id="No Upgrade"), pytest.param(860, id="v8.6"), pytest.param(870, id="v8.7")] + ) def test_lifecycle( - self, - client: TestClient, - user_access_token: str, - study_id: str, + self, client: TestClient, user_access_token: str, study_id: str, admin_access_token: str, version: int ) -> None: # ============================= - # THERMAL CLUSTER CREATION + # STUDY UPGRADE # ============================= + if version != 0: + res = client.put( + f"/v1/studies/{study_id}/upgrade", + headers={"Authorization": f"Bearer {admin_access_token}"}, + params={"target_version": version}, + ) + res.raise_for_status() + task_id = res.json() + task = wait_task_completion(client, admin_access_token, task_id) + from antarest.core.tasks.model import TaskStatus + + assert task.status == TaskStatus.COMPLETED, task + + # ================================= + # UPDATE EXPECTED POLLUTANTS LIST + # ================================= + + # noinspection SpellCheckingInspection + pollutants_names = ["nh3", "nmvoc", "nox", "op1", "op2", "op3", "op4", "op5", "pm10", "pm25", "pm5", "so2"] + pollutants_values = 0.0 if version >= 860 else None + for existing_cluster in EXISTING_CLUSTERS: + existing_cluster.update({p: pollutants_values for p in pollutants_names}) + existing_cluster.update( + { + "costGeneration": "SetManually" if version == 870 else None, + "efficiency": 100.0 if version == 870 else None, + "variableOMCost": 0.0 if version == 870 else None, + } + ) + + # ========================== + # THERMAL CLUSTER CREATION + # ========================== + area_id = transform_name_to_id("FR") fr_gas_conventional = "FR_Gas conventional" @@ -430,18 +371,15 @@ def test_lifecycle( fr_gas_conventional_cfg = { **fr_gas_conventional_props, "id": fr_gas_conventional_id, - "nh3": None, - "nmvoc": None, - "nox": None, - "op1": None, - "op2": None, - "op3": None, - "op4": None, - "op5": None, - "pm10": None, - "pm25": None, - "pm5": None, - "so2": None, + **{p: pollutants_values for p in pollutants_names}, + } + fr_gas_conventional_cfg = { + **fr_gas_conventional_cfg, + **{ + "costGeneration": "SetManually" if version == 870 else None, + "efficiency": 100.0 if version == 870 else None, + "variableOMCost": 0.0 if version == 870 else None, + }, } assert res.json() == fr_gas_conventional_cfg @@ -453,9 +391,9 @@ def test_lifecycle( assert res.status_code == 200, res.json() assert res.json() == fr_gas_conventional_cfg - # ============================= + # ========================== # THERMAL CLUSTER MATRICES - # ============================= + # ========================== matrix = np.random.randint(0, 2, size=(8760, 1)).tolist() matrix_path = f"input/thermal/prepro/{area_id}/{fr_gas_conventional_id.lower()}/data" @@ -554,6 +492,24 @@ def test_lifecycle( assert res.status_code == 200, res.json() assert res.json() == fr_gas_conventional_cfg + # Update with a pollutant. Should succeed even with versions prior to v8.6 + res = client.patch( + f"/v1/studies/{study_id}/areas/{area_id}/clusters/thermal/{fr_gas_conventional_id}", + headers={"Authorization": f"Bearer {user_access_token}"}, + json={"nox": 10.0}, + ) + assert res.status_code == 200 + assert res.json()["nox"] == 10.0 + + # Update with the field `efficiency`. Should succeed even with versions prior to v8.7 + res = client.patch( + f"/v1/studies/{study_id}/areas/{area_id}/clusters/thermal/{fr_gas_conventional_id}", + headers={"Authorization": f"Bearer {user_access_token}"}, + json={"efficiency": 97.0}, + ) + assert res.status_code == 200 + assert res.json()["efficiency"] == 97.0 + # ============================= # THERMAL CLUSTER DUPLICATION # ============================= @@ -570,6 +526,11 @@ def test_lifecycle( duplicated_config["name"] = new_name duplicated_id = transform_name_to_id(new_name, lower=False) duplicated_config["id"] = duplicated_id + # takes the update into account + if version >= 860: + duplicated_config["nox"] = 10 + if version >= 870: + duplicated_config["efficiency"] = 97.0 assert res.json() == duplicated_config # asserts the matrix has also been duplicated @@ -582,10 +543,109 @@ def test_lifecycle( assert res.status_code == 200 assert res.json()["data"] == matrix + # ============================= + # THERMAL CLUSTER VALIDATION + # ============================= + + # Everything is fine at the beginning + res = client.get( + f"/v1/studies/{study_id}/areas/{area_id}/clusters/thermal/{fr_gas_conventional_id}/validate", + headers={"Authorization": f"Bearer {user_access_token}"}, + ) + assert res.status_code == 200 + assert res.json() is True + + # Modifies series matrix with wrong length (!= 8760) + _upload_matrix( + client, + user_access_token, + study_id, + f"input/thermal/series/{area_id}/{fr_gas_conventional_id.lower()}/series", + pd.DataFrame(np.random.randint(0, 10, size=(4, 1))), + ) + + # Validation should fail + res = client.get( + f"/v1/studies/{study_id}/areas/{area_id}/clusters/thermal/{fr_gas_conventional_id}/validate", + headers={"Authorization": f"Bearer {user_access_token}"}, + ) + assert res.status_code == 422 + obj = res.json() + assert obj["exception"] == "WrongMatrixHeightError" + assert obj["description"] == "The matrix series should have 8760 rows, currently: 4" + + # Update with the right length + _upload_matrix( + client, + user_access_token, + study_id, + f"input/thermal/series/{area_id}/{fr_gas_conventional_id.lower()}/series", + pd.DataFrame(np.random.randint(0, 10, size=(8760, 4))), + ) + + # Validation should succeed again + res = client.get( + f"/v1/studies/{study_id}/areas/{area_id}/clusters/thermal/{fr_gas_conventional_id}/validate", + headers={"Authorization": f"Bearer {user_access_token}"}, + ) + assert res.status_code == 200 + assert res.json() is True + + if version >= 870: + # Adds a CO2Cost matrix with different columns size + _upload_matrix( + client, + user_access_token, + study_id, + f"input/thermal/series/{area_id}/{fr_gas_conventional_id.lower()}/CO2Cost", + pd.DataFrame(np.random.randint(0, 10, size=(8760, 3))), + ) + + # Validation should fail + res = client.get( + f"/v1/studies/{study_id}/areas/{area_id}/clusters/thermal/{fr_gas_conventional_id}/validate", + headers={"Authorization": f"Bearer {user_access_token}"}, + ) + assert res.status_code == 422 + obj = res.json() + assert obj["exception"] == "MatrixWidthMismatchError" + pattern = r".*'series'.*4.*'CO2Cost'.*3" + assert re.match(pattern, obj["description"]) + # ============================= # THERMAL CLUSTER DELETION # ============================= + # Here is a Binding Constraint that references the thermal cluster.: + bc_obj = { + "name": "Binding Constraint", + "enabled": True, + "time_step": "hourly", + "operator": "less", + "terms": [ + { + "id": f"{area_id}.{fr_gas_conventional_id.lower()}", + "weight": 2, + "offset": 5, + "data": {"area": area_id, "cluster": fr_gas_conventional_id.lower()}, + } + ], + "comments": "New API", + } + matrix = np.random.randint(0, 1000, size=(8784, 3)) + if version < 870: + bc_obj["values"] = matrix.tolist() + else: + bc_obj["lessTermMatrix"] = matrix.tolist() + + # noinspection SpellCheckingInspection + res = client.post( + f"/v1/studies/{study_id}/bindingconstraints", + json=bc_obj, + headers={"Authorization": f"Bearer {user_access_token}"}, + ) + assert res.status_code in {200, 201}, res.json() + # To delete a thermal cluster, we need to provide its ID. res = client.request( "DELETE", @@ -596,6 +656,15 @@ def test_lifecycle( assert res.status_code == 204, res.json() assert res.text in {"", "null"} # Old FastAPI versions return 'null'. + # When we delete a thermal cluster, we should also delete the binding constraints that reference it. + # noinspection SpellCheckingInspection + res = client.get( + f"/v1/studies/{study_id}/bindingconstraints", + headers={"Authorization": f"Bearer {user_access_token}"}, + ) + assert res.status_code == 200, res.json() + assert len(res.json()) == 0 + # If the thermal cluster list is empty, the deletion should be a no-op. res = client.request( "DELETE", @@ -801,8 +870,8 @@ def test_lifecycle( ) assert res.status_code == 404, res.json() obj = res.json() - assert obj["description"] == f"Cluster: '{unknown_id}' not found" - assert obj["exception"] == "ClusterNotFound" + assert f"'{unknown_id}' not found" in obj["description"] + assert obj["exception"] == "ThermalClusterNotFound" # Cannot duplicate with an existing id res = client.post( @@ -814,7 +883,7 @@ def test_lifecycle( obj = res.json() description = obj["description"] assert new_name.upper() in description - assert obj["exception"] == "ClusterAlreadyExists" + assert obj["exception"] == "DuplicateThermalCluster" @pytest.fixture(name="base_study_id") def base_study_id_fixture(self, request: t.Any, client: TestClient, user_access_token: str) -> str: diff --git a/tests/integration/test_integration.py b/tests/integration/test_integration.py index c07f13c59c..8c03873992 100644 --- a/tests/integration/test_integration.py +++ b/tests/integration/test_integration.py @@ -6,28 +6,14 @@ from starlette.testclient import TestClient -from antarest.core.model import PublicMode from antarest.launcher.model import LauncherLoadDTO -from antarest.study.business.adequacy_patch_management import PriceTakingOrder -from antarest.study.business.area_management import AreaType, LayerInfoDTO -from antarest.study.business.areas.properties_management import AdequacyPatchMode -from antarest.study.business.areas.renewable_management import TimeSeriesInterpretation +from antarest.study.business.area_management import LayerInfoDTO from antarest.study.business.general_management import Mode from antarest.study.business.optimization_management import ( SimplexOptimizationRange, TransmissionCapacities, UnfeasibleProblemBehavior, ) -from antarest.study.business.table_mode_management import ( - FIELDS_INFO_BY_TYPE, - AssetType, - BindingConstraintOperator, - TableTemplateType, - TransmissionCapacity, -) -from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import BindingConstraintFrequency -from antarest.study.storage.rawstudy.model.filesystem.config.renewable import RenewableClusterGroup -from antarest.study.storage.rawstudy.model.filesystem.config.thermal import LawOption, LocalTSGenerationBehavior from antarest.study.storage.variantstudy.model.command.common import CommandName from tests.integration.assets import ASSETS_DIR from tests.integration.utils import wait_for @@ -298,7 +284,7 @@ def test_main(client: TestClient, admin_access_token: str, study_id: str) -> Non res = client.get("/v1/launcher/load", headers=admin_headers) assert res.status_code == 200, res.json() - launcher_load = LauncherLoadDTO.parse_obj(res.json()) + launcher_load = LauncherLoadDTO(**res.json()) assert launcher_load.allocated_cpu_rate == 100 / (os.cpu_count() or 1) assert launcher_load.cluster_load_rate == 100 / (os.cpu_count() or 1) assert launcher_load.nb_queued_jobs == 0 @@ -398,10 +384,10 @@ def test_matrix(client: TestClient, admin_access_token: str, study_id: str) -> N assert res.status_code == 200 -def test_area_management(client: TestClient, admin_access_token: str, study_id: str) -> None: +def test_area_management(client: TestClient, admin_access_token: str) -> None: admin_headers = {"Authorization": f"Bearer {admin_access_token}"} - created = client.post("/v1/studies?name=foo", headers=admin_headers) + created = client.post("/v1/studies", headers=admin_headers, params={"name": "foo", "version": 870}) study_id = created.json() res_areas = client.get(f"/v1/studies/{study_id}/areas", headers=admin_headers) assert res_areas.json() == [ @@ -420,23 +406,26 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: headers=admin_headers, json={ "name": "area 1", - "type": AreaType.AREA.value, + "type": "AREA", "metadata": {"country": "FR", "tags": ["a"]}, }, ) + assert res.status_code == 200, res.json() + + # Test area creation with duplicate name res = client.post( f"/v1/studies/{study_id}/areas", headers=admin_headers, json={ - "name": "area 1", - "type": AreaType.AREA.value, + "name": "Area 1", # Same name but with different case + "type": "AREA", "metadata": {"country": "FR"}, }, ) - assert res.status_code == 500 + assert res.status_code == 409, res.json() assert res.json() == { - "description": "Area 'area 1' already exists and could not be created", - "exception": "CommandApplicationError", + "description": "Area 'Area 1' already exists and could not be created", + "exception": "DuplicateAreaName", } client.post( @@ -444,7 +433,7 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: headers=admin_headers, json={ "name": "area 2", - "type": AreaType.AREA.value, + "type": "AREA", "metadata": {"country": "DE"}, }, ) @@ -518,8 +507,8 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: "args": { "name": "binding constraint 1", "enabled": True, - "time_step": BindingConstraintFrequency.HOURLY.value, - "operator": BindingConstraintOperator.LESS.value, + "time_step": "hourly", + "operator": "less", "coeffs": {"area 1.cluster 1": [2.0, 4]}, }, } @@ -536,8 +525,8 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: "args": { "name": "binding constraint 2", "enabled": True, - "time_step": BindingConstraintFrequency.HOURLY.value, - "operator": BindingConstraintOperator.LESS.value, + "time_step": "hourly", + "operator": "less", "coeffs": {}, }, } @@ -794,7 +783,7 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: "ntcBetweenPhysicalAreasOutAdequacyPatch": True, "checkCsrCostFunction": False, "includeHurdleCostCsr": False, - "priceTakingOrder": PriceTakingOrder.DENS.value, + "priceTakingOrder": "DENS", "thresholdInitiateCurtailmentSharingRule": 0.0, "thresholdDisplayLocalMatchingRuleViolations": 0.0, "thresholdCsrVariableBoundsRelaxation": 3, @@ -805,7 +794,7 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: headers=admin_headers, json={ "ntcBetweenPhysicalAreasOutAdequacyPatch": False, - "priceTakingOrder": PriceTakingOrder.LOAD.value, + "priceTakingOrder": "Load", "thresholdDisplayLocalMatchingRuleViolations": 1.1, }, ) @@ -817,7 +806,7 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: "ntcBetweenPhysicalAreasOutAdequacyPatch": False, "checkCsrCostFunction": False, "includeHurdleCostCsr": False, - "priceTakingOrder": PriceTakingOrder.LOAD.value, + "priceTakingOrder": "Load", "thresholdInitiateCurtailmentSharingRule": 0.0, "thresholdDisplayLocalMatchingRuleViolations": 1.1, "thresholdCsrVariableBoundsRelaxation": 3, @@ -1151,9 +1140,6 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: res_properties_config_json["filterSynthesis"] = set(res_properties_config_json["filterSynthesis"]) res_properties_config_json["filterByYear"] = set(res_properties_config_json["filterByYear"]) assert res_properties_config_json == { - "color": "230,108,44", - "posX": 0.0, - "posY": 0.0, "energyCostUnsupplied": 0.0, "energyCostSpilled": 0.0, "nonDispatchPower": True, @@ -1161,16 +1147,13 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: "otherDispatchPower": True, "filterSynthesis": {"hourly", "daily", "weekly", "monthly", "annual"}, "filterByYear": {"hourly", "daily", "weekly", "monthly", "annual"}, - "adequacyPatchMode": AdequacyPatchMode.OUTSIDE.value, + "adequacyPatchMode": "outside", } client.put( f"/v1/studies/{study_id}/areas/area 1/properties/form", headers=admin_headers, json={ - "color": "123,108,96", - "posX": 3.4, - "posY": 9.0, "energyCostUnsupplied": 2.0, "energyCostSpilled": 4.0, "nonDispatchPower": False, @@ -1178,7 +1161,7 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: "otherDispatchPower": False, "filterSynthesis": ["monthly", "annual"], "filterByYear": ["hourly", "daily", "annual"], - "adequacyPatchMode": AdequacyPatchMode.INSIDE.value, + "adequacyPatchMode": "inside", }, ) res_properties_config = client.get(f"/v1/studies/{study_id}/areas/area 1/properties/form", headers=admin_headers) @@ -1186,9 +1169,6 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: res_properties_config_json["filterSynthesis"] = set(res_properties_config_json["filterSynthesis"]) res_properties_config_json["filterByYear"] = set(res_properties_config_json["filterByYear"]) assert res_properties_config_json == { - "color": "123,108,96", - "posX": 3.4, - "posY": 9.0, "energyCostUnsupplied": 2.0, "energyCostSpilled": 4.0, "nonDispatchPower": False, @@ -1196,7 +1176,7 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: "otherDispatchPower": False, "filterSynthesis": {"monthly", "annual"}, "filterByYear": {"hourly", "daily", "annual"}, - "adequacyPatchMode": AdequacyPatchMode.INSIDE.value, + "adequacyPatchMode": "inside", } # Hydro form @@ -1333,448 +1313,6 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: "ntc": {"stochasticTsStatus": False, "intraModal": False}, } - # --- TableMode START --- - - table_mode_url = f"/v1/studies/{study_id}/tablemode" - - # Table Mode - Area - - res_table_data = client.get( - table_mode_url, - headers=admin_headers, - params={ - "table_type": TableTemplateType.AREA.value, - "columns": ",".join(FIELDS_INFO_BY_TYPE[TableTemplateType.AREA]), - }, - ) - res_table_data_json = res_table_data.json() - assert res_table_data_json == { - "area 1": { - "nonDispatchablePower": False, - "dispatchableHydroPower": False, - "otherDispatchablePower": False, - "averageUnsuppliedEnergyCost": 2.0, - "spreadUnsuppliedEnergyCost": 0.0, - "averageSpilledEnergyCost": 4.0, - "spreadSpilledEnergyCost": 0.0, - "filterSynthesis": "monthly, annual", - "filterYearByYear": "hourly, daily, annual", - "adequacyPatchMode": AdequacyPatchMode.INSIDE.value, - }, - "area 2": { - "nonDispatchablePower": True, - "dispatchableHydroPower": True, - "otherDispatchablePower": True, - "averageUnsuppliedEnergyCost": 0.0, - "spreadUnsuppliedEnergyCost": 0.0, - "averageSpilledEnergyCost": 0.0, - "spreadSpilledEnergyCost": 0.0, - "filterSynthesis": "hourly, daily, weekly, monthly, annual", - "filterYearByYear": "hourly, daily, weekly, monthly, annual", - "adequacyPatchMode": AdequacyPatchMode.OUTSIDE.value, - }, - } - - client.put( - table_mode_url, - headers=admin_headers, - params={ - "table_type": TableTemplateType.AREA.value, - }, - json={ - "area 1": { - "nonDispatchablePower": True, - "spreadSpilledEnergyCost": 1.1, - "filterYearByYear": "monthly, annual", - "adequacyPatchMode": AdequacyPatchMode.OUTSIDE.value, - }, - "area 2": { - "nonDispatchablePower": False, - "spreadSpilledEnergyCost": 3.0, - "filterSynthesis": "hourly", - "adequacyPatchMode": AdequacyPatchMode.INSIDE.value, - }, - }, - ) - res_table_data = client.get( - table_mode_url, - headers=admin_headers, - params={ - "table_type": TableTemplateType.AREA.value, - "columns": ",".join(list(FIELDS_INFO_BY_TYPE[TableTemplateType.AREA])), - }, - ) - res_table_data_json = res_table_data.json() - assert res_table_data_json == { - "area 1": { - "nonDispatchablePower": True, - "dispatchableHydroPower": False, - "otherDispatchablePower": False, - "averageUnsuppliedEnergyCost": 2.0, - "spreadUnsuppliedEnergyCost": 0.0, - "averageSpilledEnergyCost": 4.0, - "spreadSpilledEnergyCost": 1.1, - "filterSynthesis": "monthly, annual", - "filterYearByYear": "monthly, annual", - "adequacyPatchMode": AdequacyPatchMode.OUTSIDE.value, - }, - "area 2": { - "nonDispatchablePower": False, - "dispatchableHydroPower": True, - "otherDispatchablePower": True, - "averageUnsuppliedEnergyCost": 0.0, - "spreadUnsuppliedEnergyCost": 0.0, - "averageSpilledEnergyCost": 0.0, - "spreadSpilledEnergyCost": 3.0, - "filterSynthesis": "hourly", - "filterYearByYear": "hourly, daily, weekly, monthly, annual", - "adequacyPatchMode": AdequacyPatchMode.INSIDE.value, - }, - } - - # Table Mode - Link - - res_table_data = client.get( - table_mode_url, - headers=admin_headers, - params={ - "table_type": TableTemplateType.LINK.value, - "columns": ",".join(FIELDS_INFO_BY_TYPE[TableTemplateType.LINK]), - }, - ) - res_table_data_json = res_table_data.json() - assert res_table_data_json == { - "area 1 / area 2": { - "hurdlesCost": False, - "loopFlow": False, - "usePhaseShifter": False, - "transmissionCapacities": "enabled", - "assetType": "ac", - "linkStyle": "plain", - "linkWidth": True, - "displayComments": True, - "filterSynthesis": "hourly, daily, weekly, monthly, annual", - "filterYearByYear": "hourly, daily, weekly, monthly, annual", - } - } - - client.put( - table_mode_url, - headers=admin_headers, - params={ - "table_type": TableTemplateType.LINK.value, - }, - json={ - "area 1 / area 2": { - "hurdlesCost": True, - "transmissionCapacities": TransmissionCapacity.IGNORE.value, - "assetType": AssetType.GAZ.value, - "filterSynthesis": "daily,annual", - } - }, - ) - res_table_data = client.get( - table_mode_url, - headers=admin_headers, - params={ - "table_type": TableTemplateType.LINK.value, - "columns": ",".join(FIELDS_INFO_BY_TYPE[TableTemplateType.LINK]), - }, - ) - res_table_data_json = res_table_data.json() - assert res_table_data_json == { - "area 1 / area 2": { - "hurdlesCost": True, - "loopFlow": False, - "usePhaseShifter": False, - "transmissionCapacities": "ignore", - "assetType": "gaz", - "linkStyle": "plain", - "linkWidth": True, - "displayComments": True, - "filterSynthesis": "daily,annual", - "filterYearByYear": "hourly, daily, weekly, monthly, annual", - } - } - - # Table Mode - Cluster - - res_table_data = client.get( - table_mode_url, - headers=admin_headers, - params={ - "table_type": TableTemplateType.CLUSTER.value, - "columns": ",".join(FIELDS_INFO_BY_TYPE[TableTemplateType.CLUSTER]), - }, - ) - res_table_data_json = res_table_data.json() - assert res_table_data_json == { - "area 1 / cluster 1": { - "group": "", - "enabled": True, - "mustRun": False, - "unitCount": 0, - "nominalCapacity": 0, - "minStablePower": 0, - "spinning": 0, - "minUpTime": 1, - "minDownTime": 1, - "co2": 0, - "marginalCost": 0, - "fixedCost": 0, - "startupCost": 0, - "marketBidCost": 0, - "spreadCost": 0, - "tsGen": "use global", - "volatilityForced": 0, - "volatilityPlanned": 0, - "lawForced": "uniform", - "lawPlanned": "uniform", - }, - "area 2 / cluster 2": { - "group": "", - "enabled": True, - "mustRun": False, - "unitCount": 0, - "nominalCapacity": 0, - "minStablePower": 0, - "spinning": 0, - "minUpTime": 1, - "minDownTime": 1, - "co2": 0, - "marginalCost": 0, - "fixedCost": 0, - "startupCost": 0, - "marketBidCost": 0, - "spreadCost": 0, - "tsGen": "use global", - "volatilityForced": 0, - "volatilityPlanned": 0, - "lawForced": "uniform", - "lawPlanned": "uniform", - }, - } - - client.put( - table_mode_url, - headers=admin_headers, - params={ - "table_type": TableTemplateType.CLUSTER.value, - }, - json={ - "area 1 / cluster 1": { - "enabled": False, - "unitCount": 3, - "spinning": 8, - "tsGen": LocalTSGenerationBehavior.FORCE_GENERATION.value, - "lawPlanned": LawOption.GEOMETRIC.value, - }, - "area 2 / cluster 2": { - "nominalCapacity": 2, - }, - }, - ) - res_table_data = client.get( - table_mode_url, - headers=admin_headers, - params={ - "table_type": TableTemplateType.CLUSTER.value, - "columns": ",".join(FIELDS_INFO_BY_TYPE[TableTemplateType.CLUSTER]), - }, - ) - res_table_data_json = res_table_data.json() - assert res_table_data_json == { - "area 1 / cluster 1": { - "group": "", - "enabled": False, - "mustRun": False, - "unitCount": 3, - "nominalCapacity": 0, - "minStablePower": 0, - "spinning": 8, - "minUpTime": 1, - "minDownTime": 1, - "co2": 0, - "marginalCost": 0, - "fixedCost": 0, - "startupCost": 0, - "marketBidCost": 0, - "spreadCost": 0, - "tsGen": "force generation", - "volatilityForced": 0, - "volatilityPlanned": 0, - "lawForced": "uniform", - "lawPlanned": "geometric", - }, - "area 2 / cluster 2": { - "group": "", - "enabled": True, - "mustRun": False, - "unitCount": 0, - "nominalCapacity": 2, - "minStablePower": 0, - "spinning": 0, - "minUpTime": 1, - "minDownTime": 1, - "co2": 0, - "marginalCost": 0, - "fixedCost": 0, - "startupCost": 0, - "marketBidCost": 0, - "spreadCost": 0, - "tsGen": "use global", - "volatilityForced": 0, - "volatilityPlanned": 0, - "lawForced": "uniform", - "lawPlanned": "uniform", - }, - } - - # Table Mode - Renewable - - res_table_data = client.get( - table_mode_url, - headers=admin_headers, - params={ - "table_type": TableTemplateType.RENEWABLE.value, - "columns": ",".join(FIELDS_INFO_BY_TYPE[TableTemplateType.RENEWABLE]), - }, - ) - res_table_data_json = res_table_data.json() - assert res_table_data_json == { - "area 1 / cluster renewable 1": { - "group": "", - "tsInterpretation": TimeSeriesInterpretation.POWER_GENERATION.value, - "enabled": True, - "unitCount": 0, - "nominalCapacity": 0, - }, - "area 2 / cluster renewable 2": { - "group": "", - "tsInterpretation": TimeSeriesInterpretation.POWER_GENERATION.value, - "enabled": True, - "unitCount": 0, - "nominalCapacity": 0, - }, - } - - client.put( - table_mode_url, - headers=admin_headers, - params={ - "table_type": TableTemplateType.RENEWABLE.value, - }, - json={ - "area 1 / cluster renewable 1": { - "tsInterpretation": TimeSeriesInterpretation.PRODUCTION_FACTOR.value, - "enabled": False, - }, - "area 2 / cluster renewable 2": { - "unitCount": 2, - "nominalCapacity": 13, - }, - }, - ) - res_table_data = client.get( - table_mode_url, - headers=admin_headers, - params={ - "table_type": TableTemplateType.RENEWABLE.value, - "columns": ",".join(FIELDS_INFO_BY_TYPE[TableTemplateType.RENEWABLE]), - }, - ) - res_table_data_json = res_table_data.json() - assert res_table_data_json == { - "area 1 / cluster renewable 1": { - "group": "", - "tsInterpretation": TimeSeriesInterpretation.PRODUCTION_FACTOR.value, - "enabled": False, - "unitCount": 0, - "nominalCapacity": 0, - }, - "area 2 / cluster renewable 2": { - "group": "", - "tsInterpretation": TimeSeriesInterpretation.POWER_GENERATION.value, - "enabled": True, - "unitCount": 2, - "nominalCapacity": 13, - }, - } - - # Table Mode - Binding Constraint - - res_table_data = client.get( - table_mode_url, - headers=admin_headers, - params={ - "table_type": TableTemplateType.BINDING_CONSTRAINT.value, - "columns": ",".join(FIELDS_INFO_BY_TYPE[TableTemplateType.BINDING_CONSTRAINT]), - }, - ) - res_table_data_json = res_table_data.json() - assert res_table_data_json == { - "binding constraint 1": { - "enabled": True, - "type": BindingConstraintFrequency.HOURLY.value, - "operator": BindingConstraintOperator.LESS.value, - }, - "binding constraint 2": { - "enabled": True, - "type": BindingConstraintFrequency.HOURLY.value, - "operator": BindingConstraintOperator.LESS.value, - }, - } - - client.put( - table_mode_url, - headers=admin_headers, - params={ - "table_type": TableTemplateType.BINDING_CONSTRAINT.value, - }, - json={ - "binding constraint 1": { - "enabled": False, - "operator": BindingConstraintOperator.BOTH.value, - }, - "binding constraint 2": { - "type": BindingConstraintFrequency.WEEKLY.value, - "operator": BindingConstraintOperator.EQUAL.value, - }, - }, - ) - res_table_data = client.get( - table_mode_url, - headers=admin_headers, - params={ - "table_type": TableTemplateType.BINDING_CONSTRAINT.value, - "columns": ",".join(FIELDS_INFO_BY_TYPE[TableTemplateType.BINDING_CONSTRAINT]), - }, - ) - res_table_data_json = res_table_data.json() - assert res_table_data_json == { - "binding constraint 1": { - "enabled": False, - "type": BindingConstraintFrequency.HOURLY.value, - "operator": BindingConstraintOperator.BOTH.value, - }, - "binding constraint 2": { - "enabled": True, - "type": BindingConstraintFrequency.WEEKLY.value, - "operator": BindingConstraintOperator.EQUAL.value, - }, - } - - res = client.get(f"/v1/studies/{study_id}/bindingconstraints/binding constraint 1", headers=admin_headers) - binding_constraint_1 = res.json() - assert res.status_code == 200 - - constraint = binding_constraint_1["constraints"][0] - assert constraint["id"] == "area 1.cluster 1" - assert constraint["weight"] == 2.0 - assert constraint["offset"] == 4.0 - - # --- TableMode END --- - # Renewable form res = client.put( @@ -1782,7 +1320,7 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: headers=admin_headers, json={ "name": "cluster renewable 1 renamed", - "tsInterpretation": TimeSeriesInterpretation.PRODUCTION_FACTOR, + "tsInterpretation": "production-factor", "unitCount": 9, "enabled": False, "nominalCapacity": 3, @@ -1796,11 +1334,11 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: ) expected = { "enabled": False, - "group": RenewableClusterGroup.OTHER1, # Default group used when not specified. + "group": "Other RES 1", # Default group used when not specified. "id": "cluster renewable 1", "name": "cluster renewable 1 renamed", "nominalCapacity": 3.0, - "tsInterpretation": TimeSeriesInterpretation.PRODUCTION_FACTOR, + "tsInterpretation": "production-factor", "unitCount": 9, } assert res.status_code == 200, res.json() @@ -1842,6 +1380,9 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: "op3": 3, "op4": 2.4, "op5": 0, + "costGeneration": "SetManually", + "efficiency": 100.0, + "variableOMCost": 0.0, } res = client.put( # This URL is deprecated, but we must check it for backward compatibility. @@ -1885,11 +1426,11 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: "color_r": 255, "color_g": 0, "color_b": 100, - "layers": 0, + "layers": "0", }, "layerX": {"0": 100}, "layerY": {"0": 100}, - "layerColor": {"0": "255 , 0 , 100"}, + "layerColor": {"0": "255, 0, 100"}, }, "area 2": { "ui": { @@ -1902,7 +1443,7 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: }, "layerX": {"0": 0, "1": 105}, "layerY": {"0": 0, "1": 105}, - "layerColor": {"0": "230 , 108 , 44", "1": "255 , 10 , 100"}, + "layerColor": {"0": "230, 108, 44", "1": "255, 10, 100"}, }, } @@ -1927,7 +1468,7 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: "min-stable-power": None, "min-up-time": None, "name": "cluster 2", - "nominalcapacity": 2, + "nominalcapacity": 0, "spinning": None, "spread-cost": None, "type": None, @@ -2053,7 +1594,7 @@ def test_import(client: TestClient, admin_access_token: str, study_id: str) -> N ).json() res = client.get(f"v1/studies/{uuid}", headers=admin_headers).json() assert res["groups"] == [{"id": "admin", "name": "admin"}] - assert res["public_mode"] == PublicMode.NONE + assert res["public_mode"] == "NONE" # Create user George who belongs to no group client.post( @@ -2073,7 +1614,7 @@ def test_import(client: TestClient, admin_access_token: str, study_id: str) -> N ).json() res = client.get(f"v1/studies/{uuid}", headers=georges_headers).json() assert res["groups"] == [] - assert res["public_mode"] == PublicMode.READ + assert res["public_mode"] == "READ" # Study importer works for 7z files res = client.post( @@ -2141,7 +1682,7 @@ def test_copy(client: TestClient, admin_access_token: str, study_id: str) -> Non # asserts that it has admin groups and PublicMode to NONE res = client.get(f"/v1/studies/{copied.json()}", headers=admin_headers).json() assert res["groups"] == [{"id": "admin", "name": "admin"}] - assert res["public_mode"] == PublicMode.NONE + assert res["public_mode"] == "NONE" # Connect with user George who belongs to no group res = client.post("/v1/login", json={"username": "George", "password": "mypass"}) @@ -2156,4 +1697,4 @@ def test_copy(client: TestClient, admin_access_token: str, study_id: str) -> Non # asserts that it has no groups and PublicMode to READ res = client.get(f"/v1/studies/{copied.json()}", headers=admin_headers).json() assert res["groups"] == [] - assert res["public_mode"] == PublicMode.READ + assert res["public_mode"] == "READ" diff --git a/tests/integration/test_integration_variantmanager_tool.py b/tests/integration/test_integration_variantmanager_tool.py index f381cab3c9..4b27c84848 100644 --- a/tests/integration/test_integration_variantmanager_tool.py +++ b/tests/integration/test_integration_variantmanager_tool.py @@ -21,8 +21,7 @@ generate_study, parse_commands, ) - -test_dir: Path = Path(__file__).parent +from tests.integration.assets import ASSETS_DIR def generate_csv_string(array: npt.NDArray[np.float64]) -> str: @@ -49,27 +48,26 @@ def generate_study_with_server( f"/v1/studies/{base_study_id}/variants?name={urllib.parse.quote_plus(name)}", headers={"Authorization": f'Bearer {admin_credentials["access_token"]}'}, ) + assert res.status_code == 200, res.json() variant_id = res.json() - assert res.status_code == 200 generator = RemoteVariantGenerator(variant_id, session=client, token=admin_credentials["access_token"]) return generator.apply_commands(commands, matrices_dir), variant_id def test_variant_manager(app: FastAPI, tmp_path: str) -> None: client = TestClient(app, raise_server_exceptions=False) - commands = parse_commands(test_dir / "assets" / "commands1.json") - matrix_dir = Path(tmp_path) / "empty_matrix_store" + commands = parse_commands(ASSETS_DIR / "commands1.json") + matrix_dir = tmp_path / "empty_matrix_store" matrix_dir.mkdir(parents=True, exist_ok=True) res, study_id = generate_study_with_server(client, "test", "720", commands, matrix_dir) assert res is not None and res.success def test_parse_commands(tmp_path: str, app: FastAPI) -> None: - base_dir = test_dir / "assets" - export_path = Path(tmp_path) / "commands" + export_path = tmp_path / "commands" study = "base_study" - study_path = Path(tmp_path) / study - with ZipFile(base_dir / "base_study.zip") as zip_output: + study_path = tmp_path / study + with ZipFile(ASSETS_DIR / "base_study.zip") as zip_output: zip_output.extractall(path=tmp_path) output_dir = Path(export_path) / study study_info = IniReader().read(study_path / "study.antares") @@ -83,7 +81,7 @@ def test_parse_commands(tmp_path: str, app: FastAPI) -> None: ) res, study_id = generate_study_with_server(client, name, version, commands, output_dir / MATRIX_STORE_DIR) assert res is not None and res.success - generated_study_path = Path(tmp_path) / "internal_workspace" / study_id / "snapshot" + generated_study_path = tmp_path / "internal_workspace" / study_id / "snapshot" assert generated_study_path.exists() and generated_study_path.is_dir() single_column_empty_items = [ @@ -188,20 +186,19 @@ def test_parse_commands(tmp_path: str, app: FastAPI) -> None: def test_diff_local(tmp_path: Path) -> None: - base_dir = test_dir / "assets" - export_path = Path(tmp_path) / "generation_result" + export_path = tmp_path / "generation_result" base_study = "base_study" variant_study = "variant_study" output_study_commands = export_path / "output_study_commands" - output_study_path = Path(tmp_path) / base_study + output_study_path = tmp_path / base_study base_study_commands = export_path / base_study variant_study_commands = export_path / variant_study - variant_study_path = Path(tmp_path) / variant_study + variant_study_path = tmp_path / variant_study for study in [base_study, variant_study]: - with ZipFile(base_dir / f"{study}.zip") as zip_output: + with ZipFile(ASSETS_DIR / f"{study}.zip") as zip_output: zip_output.extractall(path=tmp_path) - extract_commands(Path(tmp_path) / study, export_path / study) + extract_commands(tmp_path / study, export_path / study) generate_study(base_study_commands, None, str(export_path / "base_generated")) generate_study( diff --git a/tests/launcher/test_slurm_launcher.py b/tests/launcher/test_slurm_launcher.py index a3a8cfe90b..e1c69f63d4 100644 --- a/tests/launcher/test_slurm_launcher.py +++ b/tests/launcher/test_slurm_launcher.py @@ -10,7 +10,6 @@ from antareslauncher.data_repo.data_repo_tinydb import DataRepoTinydb from antareslauncher.main import MainParameters from antareslauncher.study_dto import StudyDTO -from sqlalchemy.orm import Session # type: ignore from antarest.core.config import Config, LauncherConfig, NbCoresConfig, SlurmConfig from antarest.launcher.adapters.abstractlauncher import LauncherInitException @@ -37,7 +36,7 @@ def launcher_config(tmp_path: Path) -> Config: "key_password": "password", "password": "password", "default_wait_time": 10, - "default_time_limit": 20, + "default_time_limit": MAX_TIME_LIMIT, "default_json_db_name": "antares.db", "slurm_script_path": "/path/to/slurm/launcher.sh", "partition": "fake_partition", @@ -203,11 +202,14 @@ def test_extra_parameters(launcher_config: Config) -> None: launcher_params = apply_params(LauncherParametersDTO(nb_cpu=999)) assert launcher_params.n_cpu == slurm_config.nb_cores.default # out of range + launcher_params = apply_params(LauncherParametersDTO.construct(time_limit=None)) + assert launcher_params.time_limit == MIN_TIME_LIMIT + launcher_params = apply_params(LauncherParametersDTO(time_limit=10)) assert launcher_params.time_limit == MIN_TIME_LIMIT launcher_params = apply_params(LauncherParametersDTO(time_limit=999999999)) - assert launcher_params.time_limit == MAX_TIME_LIMIT - 3600 + assert launcher_params.time_limit == MAX_TIME_LIMIT launcher_params = apply_params(LauncherParametersDTO(time_limit=99999)) assert launcher_params.time_limit == 99999 diff --git a/tests/storage/business/assets/little_study_700.zip b/tests/storage/business/assets/little_study_700.zip index 721a9b9f44..e9a34f5f49 100644 Binary files a/tests/storage/business/assets/little_study_700.zip and b/tests/storage/business/assets/little_study_700.zip differ diff --git a/tests/storage/business/test_arealink_manager.py b/tests/storage/business/test_arealink_manager.py index 4caee7b7bd..a8beff5fc0 100644 --- a/tests/storage/business/test_arealink_manager.py +++ b/tests/storage/business/test_arealink_manager.py @@ -11,7 +11,7 @@ from antarest.core.utils.fastapi_sqlalchemy import db from antarest.matrixstore.repository import MatrixContentRepository from antarest.matrixstore.service import SimpleMatrixService -from antarest.study.business.area_management import AreaCreationDTO, AreaManager, AreaType, AreaUI +from antarest.study.business.area_management import AreaCreationDTO, AreaManager, AreaType, UpdateAreaUi from antarest.study.business.link_management import LinkInfoDTO, LinkManager from antarest.study.model import Patch, PatchArea, PatchCluster, RawStudy, StudyAdditionalData from antarest.study.repository import StudyMetadataRepository @@ -111,7 +111,7 @@ def test_area_crud(empty_study: FileStudy, matrix_service: SimpleMatrixService): assert len(empty_study.config.areas.keys()) == 1 assert json.loads((empty_study.config.study_path / "patch.json").read_text())["areas"]["test"]["country"] is None - area_manager.update_area_ui(study, "test", AreaUI(x=100, y=200, color_rgb=(255, 0, 100))) + area_manager.update_area_ui(study, "test", UpdateAreaUi(x=100, y=200, color_rgb=(255, 0, 100))) assert empty_study.tree.get(["input", "areas", "test", "ui", "ui"]) == { "x": 100, "y": 200, @@ -157,7 +157,7 @@ def test_area_crud(empty_study: FileStudy, matrix_service: SimpleMatrixService): assert (empty_study.config.study_path / "patch.json").exists() assert json.loads((empty_study.config.study_path / "patch.json").read_text())["areas"]["test"]["country"] == "FR" - area_manager.update_area_ui(study, "test", AreaUI(x=100, y=200, color_rgb=(255, 0, 100))) + area_manager.update_area_ui(study, "test", UpdateAreaUi(x=100, y=200, color_rgb=(255, 0, 100))) variant_study_service.append_commands.assert_called_with( variant_id, [ @@ -194,7 +194,7 @@ def test_area_crud(empty_study: FileStudy, matrix_service: SimpleMatrixService): }, { "target": "input/areas/test/ui/layerColor/0", - "data": "255 , 0 , 100", + "data": "255,0,100", }, ], ), diff --git a/tests/storage/business/test_study_service_utils.py b/tests/storage/business/test_study_service_utils.py index 623f17a55e..dcd674e0e3 100644 --- a/tests/storage/business/test_study_service_utils.py +++ b/tests/storage/business/test_study_service_utils.py @@ -104,7 +104,7 @@ def test_output_downloads_export(tmp_path: Path): }, StudyDownloadLevelDTO.WEEKLY, MatrixIndex( - start_date=str(datetime.datetime(2001, 1, 1)), + start_date=str(datetime.datetime(2018, 1, 1)), steps=51, first_week_size=7, level=StudyDownloadLevelDTO.WEEKLY, @@ -121,7 +121,7 @@ def test_output_downloads_export(tmp_path: Path): }, StudyDownloadLevelDTO.WEEKLY, MatrixIndex( - start_date=str(datetime.datetime(2002, 7, 5)), + start_date=str(datetime.datetime(2019, 7, 5)), steps=48, first_week_size=5, level=StudyDownloadLevelDTO.WEEKLY, @@ -138,7 +138,7 @@ def test_output_downloads_export(tmp_path: Path): }, StudyDownloadLevelDTO.MONTHLY, MatrixIndex( - start_date=str(datetime.datetime(2002, 7, 1)), + start_date=str(datetime.datetime(2019, 7, 1)), steps=7, first_week_size=7, level=StudyDownloadLevelDTO.MONTHLY, @@ -155,7 +155,7 @@ def test_output_downloads_export(tmp_path: Path): }, StudyDownloadLevelDTO.MONTHLY, MatrixIndex( - start_date=str(datetime.datetime(2002, 7, 1)), + start_date=str(datetime.datetime(2019, 7, 1)), steps=4, first_week_size=7, level=StudyDownloadLevelDTO.MONTHLY, @@ -172,7 +172,7 @@ def test_output_downloads_export(tmp_path: Path): }, StudyDownloadLevelDTO.HOURLY, MatrixIndex( - start_date=str(datetime.datetime(2010, 3, 5)), + start_date=str(datetime.datetime(2021, 3, 5)), steps=2304, first_week_size=3, level=StudyDownloadLevelDTO.HOURLY, @@ -189,7 +189,7 @@ def test_output_downloads_export(tmp_path: Path): }, StudyDownloadLevelDTO.ANNUAL, MatrixIndex( - start_date=str(datetime.datetime(2010, 3, 5)), + start_date=str(datetime.datetime(2021, 3, 5)), steps=1, first_week_size=3, level=StudyDownloadLevelDTO.ANNUAL, @@ -206,7 +206,7 @@ def test_output_downloads_export(tmp_path: Path): }, StudyDownloadLevelDTO.DAILY, MatrixIndex( - start_date=str(datetime.datetime(2009, 3, 3)), + start_date=str(datetime.datetime(2026, 3, 3)), steps=98, first_week_size=3, level=StudyDownloadLevelDTO.DAILY, diff --git a/tests/storage/business/test_study_version_upgrader.py b/tests/storage/business/test_study_version_upgrader.py index 357869b850..efe1e75315 100644 --- a/tests/storage/business/test_study_version_upgrader.py +++ b/tests/storage/business/test_study_version_upgrader.py @@ -1,5 +1,6 @@ import filecmp import glob +import os import re import shutil import zipfile @@ -28,12 +29,13 @@ def test_end_to_end_upgrades(tmp_path: Path): shutil.copytree(study_dir, before_upgrade_dir, dirs_exist_ok=True) old_values = get_old_settings_values(study_dir) old_areas_values = get_old_area_values(study_dir) + old_binding_constraint_values = get_old_binding_constraint_values(study_dir) # Only checks if the study_upgrader can go from the first supported version to the last one - target_version = "860" + target_version = "880" upgrade_study(study_dir, target_version) assert_study_antares_file_is_updated(study_dir, target_version) assert_settings_are_updated(study_dir, old_values) - assert_inputs_are_updated(study_dir, old_areas_values) + assert_inputs_are_updated(study_dir, old_areas_values, old_binding_constraint_values) assert not are_same_dir(study_dir, before_upgrade_dir) @@ -138,7 +140,17 @@ def get_old_area_values(tmp_path: Path) -> dict: return dico -def assert_inputs_are_updated(tmp_path: Path, dico: dict) -> None: +def get_old_binding_constraint_values(tmp_path: Path) -> dict: + dico = {} + bd_list = glob.glob(str(tmp_path / "input" / "bindingconstraints" / "*.txt")) + for txt_file in bd_list: + path_txt = Path(txt_file) + df = pandas.read_csv(path_txt, sep="\t", header=None) + dico[str(path_txt.stem)] = df + return dico + + +def assert_inputs_are_updated(tmp_path: Path, old_area_values: dict, old_binding_constraint_values: dict) -> None: input_path = tmp_path / "input" # tests 8.1 upgrade @@ -152,7 +164,7 @@ def assert_inputs_are_updated(tmp_path: Path, dico: dict) -> None: path_txt = Path(txt) old_txt = str(Path(path_txt.parent.name).joinpath(path_txt.stem)).replace("_parameters", "") df = pandas.read_csv(txt, sep="\t", header=None) - assert df.values.all() == dico[old_txt].iloc[:, 2:8].values.all() + assert df.to_numpy().all() == old_area_values[old_txt].iloc[:, 2:8].values.all() capacities = glob.glob(str(folder_path / "capacities" / "*")) for direction_txt in capacities: df_capacities = pandas.read_csv(direction_txt, sep="\t", header=None) @@ -160,10 +172,10 @@ def assert_inputs_are_updated(tmp_path: Path, dico: dict) -> None: old_txt = str(Path(direction_path.parent.parent.name).joinpath(direction_path.name)) if "indirect" in old_txt: new_txt = old_txt.replace("_indirect.txt", "") - assert df_capacities[0].values.all() == dico[new_txt].iloc[:, 0].values.all() + assert df_capacities[0].values.all() == old_area_values[new_txt].iloc[:, 0].values.all() else: new_txt = old_txt.replace("_direct.txt", "") - assert df_capacities[0].values.all() == dico[new_txt].iloc[:, 1].values.all() + assert df_capacities[0].values.all() == old_area_values[new_txt].iloc[:, 1].values.all() # tests 8.3 upgrade areas = glob.glob(str(tmp_path / "input" / "areas" / "*")) @@ -184,6 +196,34 @@ def assert_inputs_are_updated(tmp_path: Path, dico: dict) -> None: assert (st_storage_path / "list.ini").exists() assert input_path.joinpath("hydro", "series", area_id, "mingen.txt").exists() + # tests 8.7 upgrade + # binding constraint part + reader = IniReader(DUPLICATE_KEYS) + data = reader.read(input_path / "bindingconstraints" / "bindingconstraints.ini") + binding_constraints_list = list(data.keys()) + for bd in binding_constraints_list: + bd_id = data[bd]["id"] + assert data[bd]["group"] == "default" + for k, term in enumerate(["lt", "gt", "eq"]): + term_path = input_path / "bindingconstraints" / f"{bd_id}_{term}.txt" + df = pandas.read_csv(term_path, sep="\t", header=None) + assert df.to_numpy().all() == old_binding_constraint_values[bd_id].iloc[:, k].values.all() + + # thermal cluster part + for area in list_areas: + reader = IniReader(DUPLICATE_KEYS) + thermal_series_path = tmp_path / "input" / "thermal" / "series" / area + thermal_cluster_list = reader.read(tmp_path / "input" / "thermal" / "clusters" / area / "list.ini") + for cluster in thermal_cluster_list: + fuel_cost_path = thermal_series_path / cluster.lower() / "fuelCost.txt" + co2_cost_path = thermal_series_path / cluster.lower() / "CO2Cost.txt" + for path in [fuel_cost_path, co2_cost_path]: + assert path.exists() + assert os.path.getsize(path) == 0 + assert thermal_cluster_list[cluster]["costgeneration"] == "SetManually" + assert thermal_cluster_list[cluster]["efficiency"] == 100 + assert thermal_cluster_list[cluster]["variableomcost"] == 0 + def assert_folder_is_created(path: Path) -> None: assert path.is_dir() @@ -195,9 +235,23 @@ def are_same_dir(dir1, dir2) -> bool: dirs_cmp = filecmp.dircmp(dir1, dir2) if len(dirs_cmp.left_only) > 0 or len(dirs_cmp.right_only) > 0 or len(dirs_cmp.funny_files) > 0: return False + path_dir1 = Path(dir1) + path_dir2 = Path(dir2) + # check files content ignoring newline character (to avoid crashing on Windows) + for common_file in dirs_cmp.common_files: + file_1 = path_dir1 / common_file + file_2 = path_dir2 / common_file + # ignore study.ico + if common_file == "study.ico": + continue + with open(file_1, "r", encoding="utf-8") as f1: + with open(file_2, "r", encoding="utf-8") as f2: + content_1 = f1.read().splitlines(keepends=False) + content_2 = f2.read().splitlines(keepends=False) + if content_1 != content_2: + return False + # iter through common dirs recursively for common_dir in dirs_cmp.common_dirs: - path_dir1 = Path(dir1) - path_dir2 = Path(dir2) path_common_dir = Path(common_dir) new_dir1 = path_dir1 / path_common_dir new_dir2 = path_dir2 / path_common_dir diff --git a/tests/storage/business/test_xpansion_manager.py b/tests/storage/business/test_xpansion_manager.py index 1703325e8b..bb5651bcbd 100644 --- a/tests/storage/business/test_xpansion_manager.py +++ b/tests/storage/business/test_xpansion_manager.py @@ -81,6 +81,14 @@ def make_link_and_areas(empty_study: FileStudy) -> None: make_link(empty_study) +def set_up_xpansion_manager(tmp_path: Path) -> t.Tuple[FileStudy, RawStudy, XpansionManager]: + empty_study = make_empty_study(tmp_path, 810) + study = RawStudy(id="1", path=str(empty_study.config.study_path), version="810") + xpansion_manager = make_xpansion_manager(empty_study) + xpansion_manager.create_xpansion_configuration(study) + return empty_study, study, xpansion_manager + + @pytest.mark.unit_test @pytest.mark.parametrize( "version, expected_output", @@ -117,7 +125,7 @@ def test_create_configuration(tmp_path: Path, version: int, expected_output: JSO Test the creation of a configuration. """ empty_study = make_empty_study(tmp_path, version) - study = RawStudy(id="1", path=empty_study.config.study_path, version=version) + study = RawStudy(id="1", path=str(empty_study.config.study_path), version=str(version)) xpansion_manager = make_xpansion_manager(empty_study) with pytest.raises(ChildNotFoundError): @@ -135,7 +143,7 @@ def test_delete_xpansion_configuration(tmp_path: Path) -> None: Test the deletion of a configuration. """ empty_study = make_empty_study(tmp_path, 810) - study = RawStudy(id="1", path=empty_study.config.study_path, version=810) + study = RawStudy(id="1", path=str(empty_study.config.study_path), version="810") xpansion_manager = make_xpansion_manager(empty_study) with pytest.raises(ChildNotFoundError): @@ -183,7 +191,7 @@ def test_get_xpansion_settings(tmp_path: Path, version: int, expected_output: JS """ empty_study = make_empty_study(tmp_path, version) - study = RawStudy(id="1", path=empty_study.config.study_path, version=version) + study = RawStudy(id="1", path=str(empty_study.config.study_path), version=str(version)) xpansion_manager = make_xpansion_manager(empty_study) xpansion_manager.create_xpansion_configuration(study) @@ -197,12 +205,7 @@ def test_update_xpansion_settings(tmp_path: Path) -> None: """ Test the retrieval of the xpansion settings. """ - - empty_study = make_empty_study(tmp_path, 810) - study = RawStudy(id="1", path=empty_study.config.study_path, version=810) - xpansion_manager = make_xpansion_manager(empty_study) - - xpansion_manager.create_xpansion_configuration(study) + _, study, xpansion_manager = set_up_xpansion_manager(tmp_path) new_settings_obj = { "optimality_gap": 4.0, @@ -246,10 +249,7 @@ def test_update_xpansion_settings(tmp_path: Path) -> None: @pytest.mark.unit_test def test_add_candidate(tmp_path: Path) -> None: - empty_study = make_empty_study(tmp_path, 810) - study = RawStudy(id="1", path=empty_study.config.study_path, version=810) - xpansion_manager = make_xpansion_manager(empty_study) - xpansion_manager.create_xpansion_configuration(study) + empty_study, study, xpansion_manager = set_up_xpansion_manager(tmp_path) actual = empty_study.tree.get(["user", "expansion", "candidates"]) assert actual == {} @@ -298,10 +298,7 @@ def test_add_candidate(tmp_path: Path) -> None: @pytest.mark.unit_test def test_get_candidate(tmp_path: Path) -> None: - empty_study = make_empty_study(tmp_path, 810) - study = RawStudy(id="1", path=empty_study.config.study_path, version=810) - xpansion_manager = make_xpansion_manager(empty_study) - xpansion_manager.create_xpansion_configuration(study) + empty_study, study, xpansion_manager = set_up_xpansion_manager(tmp_path) assert empty_study.tree.get(["user", "expansion", "candidates"]) == {} @@ -334,10 +331,7 @@ def test_get_candidate(tmp_path: Path) -> None: @pytest.mark.unit_test def test_get_candidates(tmp_path: Path) -> None: - empty_study = make_empty_study(tmp_path, 810) - study = RawStudy(id="1", path=empty_study.config.study_path, version=810) - xpansion_manager = make_xpansion_manager(empty_study) - xpansion_manager.create_xpansion_configuration(study) + empty_study, study, xpansion_manager = set_up_xpansion_manager(tmp_path) assert empty_study.tree.get(["user", "expansion", "candidates"]) == {} @@ -372,10 +366,7 @@ def test_get_candidates(tmp_path: Path) -> None: @pytest.mark.unit_test def test_update_candidates(tmp_path: Path) -> None: - empty_study = make_empty_study(tmp_path, 810) - study = RawStudy(id="1", path=empty_study.config.study_path, version=810) - xpansion_manager = make_xpansion_manager(empty_study) - xpansion_manager.create_xpansion_configuration(study) + empty_study, study, xpansion_manager = set_up_xpansion_manager(tmp_path) assert empty_study.tree.get(["user", "expansion", "candidates"]) == {} @@ -406,10 +397,7 @@ def test_update_candidates(tmp_path: Path) -> None: @pytest.mark.unit_test def test_delete_candidate(tmp_path: Path) -> None: - empty_study = make_empty_study(tmp_path, 810) - study = RawStudy(id="1", path=empty_study.config.study_path, version=810) - xpansion_manager = make_xpansion_manager(empty_study) - xpansion_manager.create_xpansion_configuration(study) + empty_study, study, xpansion_manager = set_up_xpansion_manager(tmp_path) assert empty_study.tree.get(["user", "expansion", "candidates"]) == {} @@ -442,10 +430,7 @@ def test_delete_candidate(tmp_path: Path) -> None: @pytest.mark.unit_test def test_update_constraints(tmp_path: Path) -> None: - empty_study = make_empty_study(tmp_path, 810) - study = RawStudy(id="1", path=empty_study.config.study_path, version=810) - xpansion_manager = make_xpansion_manager(empty_study) - xpansion_manager.create_xpansion_configuration(study) + empty_study, study, xpansion_manager = set_up_xpansion_manager(tmp_path) with pytest.raises(XpansionFileNotFoundError): xpansion_manager.update_xpansion_constraints_settings(study=study, constraints_file_name="non_existent_file") @@ -464,10 +449,7 @@ def test_update_constraints(tmp_path: Path) -> None: @pytest.mark.unit_test def test_add_resources(tmp_path: Path) -> None: - empty_study = make_empty_study(tmp_path, 810) - study = RawStudy(id="1", path=empty_study.config.study_path, version=810) - xpansion_manager = make_xpansion_manager(empty_study) - xpansion_manager.create_xpansion_configuration(study) + empty_study, study, xpansion_manager = set_up_xpansion_manager(tmp_path) filename1 = "constraints1.txt" filename2 = "constraints2.txt" @@ -520,10 +502,8 @@ def test_add_resources(tmp_path: Path) -> None: @pytest.mark.unit_test def test_list_root_resources(tmp_path: Path) -> None: - empty_study = make_empty_study(tmp_path, 810) - study = RawStudy(id="1", path=empty_study.config.study_path, version=810) - xpansion_manager = make_xpansion_manager(empty_study) - xpansion_manager.create_xpansion_configuration(study) + empty_study, study, xpansion_manager = set_up_xpansion_manager(tmp_path) + constraints_file_content = b"0" constraints_file_name = "unknownfile.txt" @@ -533,10 +513,7 @@ def test_list_root_resources(tmp_path: Path) -> None: @pytest.mark.unit_test def test_get_single_constraints(tmp_path: Path) -> None: - empty_study = make_empty_study(tmp_path, 810) - study = RawStudy(id="1", path=empty_study.config.study_path, version=810) - xpansion_manager = make_xpansion_manager(empty_study) - xpansion_manager.create_xpansion_configuration(study) + empty_study, study, xpansion_manager = set_up_xpansion_manager(tmp_path) constraints_file_content = b"0" constraints_file_name = "constraints.txt" @@ -549,12 +526,18 @@ def test_get_single_constraints(tmp_path: Path) -> None: ) +@pytest.mark.unit_test +def test_get_settings_without_sensitivity(tmp_path: Path) -> None: + empty_study, study, xpansion_manager = set_up_xpansion_manager(tmp_path) + + empty_study.tree.delete(["user", "expansion", "sensitivity"]) + # should not fail even if the folder doesn't exist as it's optional + xpansion_manager.get_xpansion_settings(study) + + @pytest.mark.unit_test def test_get_all_constraints(tmp_path: Path) -> None: - empty_study = make_empty_study(tmp_path, 810) - study = RawStudy(id="1", path=empty_study.config.study_path, version=810) - xpansion_manager = make_xpansion_manager(empty_study) - xpansion_manager.create_xpansion_configuration(study) + _, study, xpansion_manager = set_up_xpansion_manager(tmp_path) filename1 = "constraints1.txt" filename2 = "constraints2.txt" @@ -576,10 +559,7 @@ def test_get_all_constraints(tmp_path: Path) -> None: @pytest.mark.unit_test def test_add_capa(tmp_path: Path) -> None: - empty_study = make_empty_study(tmp_path, 810) - study = RawStudy(id="1", path=empty_study.config.study_path, version=810) - xpansion_manager = make_xpansion_manager(empty_study) - xpansion_manager.create_xpansion_configuration(study) + empty_study, study, xpansion_manager = set_up_xpansion_manager(tmp_path) filename1 = "capa1.txt" filename2 = "capa2.txt" @@ -610,10 +590,7 @@ def test_add_capa(tmp_path: Path) -> None: @pytest.mark.unit_test def test_delete_capa(tmp_path: Path) -> None: - empty_study = make_empty_study(tmp_path, 810) - study = RawStudy(id="1", path=empty_study.config.study_path, version=810) - xpansion_manager = make_xpansion_manager(empty_study) - xpansion_manager.create_xpansion_configuration(study) + empty_study, study, xpansion_manager = set_up_xpansion_manager(tmp_path) filename1 = "capa1.txt" filename2 = "capa2.txt" @@ -636,10 +613,7 @@ def test_delete_capa(tmp_path: Path) -> None: @pytest.mark.unit_test def test_get_single_capa(tmp_path: Path) -> None: - empty_study = make_empty_study(tmp_path, 810) - study = RawStudy(id="1", path=empty_study.config.study_path, version=810) - xpansion_manager = make_xpansion_manager(empty_study) - xpansion_manager.create_xpansion_configuration(study) + _, study, xpansion_manager = set_up_xpansion_manager(tmp_path) filename1 = "capa1.txt" filename2 = "capa2.txt" @@ -664,10 +638,7 @@ def test_get_single_capa(tmp_path: Path) -> None: @pytest.mark.unit_test def test_get_all_capa(tmp_path: Path) -> None: - empty_study = make_empty_study(tmp_path, 810) - study = RawStudy(id="1", path=empty_study.config.study_path, version=810) - xpansion_manager = make_xpansion_manager(empty_study) - xpansion_manager.create_xpansion_configuration(study) + _, study, xpansion_manager = set_up_xpansion_manager(tmp_path) filename1 = "capa1.txt" filename2 = "capa2.txt" diff --git a/tests/storage/repository/filesystem/config/test_config_files.py b/tests/storage/repository/filesystem/config/test_config_files.py index ce29f1a446..f07ac8f3db 100644 --- a/tests/storage/repository/filesystem/config/test_config_files.py +++ b/tests/storage/repository/filesystem/config/test_config_files.py @@ -1,15 +1,12 @@ import logging import textwrap +import typing as t from pathlib import Path -from typing import Any, Dict from zipfile import ZipFile import pytest -from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import ( - BindingConstraintDTO, - BindingConstraintFrequency, -) +from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import BindingConstraintFrequency from antarest.study.storage.rawstudy.model.filesystem.config.files import ( _parse_links_filtering, _parse_renewables, @@ -21,6 +18,7 @@ ) from antarest.study.storage.rawstudy.model.filesystem.config.model import ( Area, + BindingConstraintDTO, DistrictSet, FileStudyTreeConfig, Link, @@ -28,7 +26,12 @@ ) from antarest.study.storage.rawstudy.model.filesystem.config.renewable import RenewableConfig from antarest.study.storage.rawstudy.model.filesystem.config.st_storage import STStorageConfig, STStorageGroup -from antarest.study.storage.rawstudy.model.filesystem.config.thermal import Thermal860Config, ThermalConfig +from antarest.study.storage.rawstudy.model.filesystem.config.thermal import ( + Thermal860Config, + Thermal870Config, + ThermalConfig, + ThermalCostGeneration, +) from tests.storage.business.assets import ASSETS_DIR @@ -214,7 +217,7 @@ def test_parse_outputs(study_path: Path) -> None: ), ], ) -def test_parse_outputs__nominal(tmp_path: Path, assets_name: str, expected: Dict[str, Any]) -> None: +def test_parse_outputs__nominal(tmp_path: Path, assets_name: str, expected: t.Dict[str, t.Any]) -> None: """ This test decompresses a zipped study (stored in the `assets` directory) into a temporary directory and executes the parsing of the outputs. @@ -376,12 +379,26 @@ def test_parse_thermal_860(study_path: Path, version, caplog) -> None: ini_path.write_text(THERMAL_860_LIST_INI) with caplog.at_level(logging.WARNING): actual = _parse_thermal(study_path, "fr") - if version >= 860: + if version == 860: expected = [ Thermal860Config(id="t1", name="t1"), Thermal860Config(id="t2", name="t2", co2=156, nh3=456), ] assert not caplog.text + elif version == 870: + expected = [ + Thermal870Config(id="t1", name="t1"), + Thermal870Config( + id="t2", + name="t2", + co2=156, + nh3=456, + cost_generation=ThermalCostGeneration.SET_MANUALLY, + efficiency=100.0, + variable_o_m_cost=0, + ), + ] + assert not caplog.text else: expected = [ThermalConfig(id="t1", name="t1")] assert "extra fields not permitted" in caplog.text diff --git a/tests/storage/repository/filesystem/test_folder_node.py b/tests/storage/repository/filesystem/test_folder_node.py index a01214eedb..7927927d7e 100644 --- a/tests/storage/repository/filesystem/test_folder_node.py +++ b/tests/storage/repository/filesystem/test_folder_node.py @@ -1,17 +1,22 @@ +import json +import textwrap +import typing as t from pathlib import Path from unittest.mock import Mock import pytest from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig +from antarest.study.storage.rawstudy.model.filesystem.factory import StudyFactory +from antarest.study.storage.rawstudy.model.filesystem.folder_node import ChildNotFoundError from antarest.study.storage.rawstudy.model.filesystem.ini_file_node import IniFileNode from antarest.study.storage.rawstudy.model.filesystem.inode import INode from antarest.study.storage.rawstudy.model.filesystem.raw_file_node import RawFileNode from antarest.study.storage.rawstudy.model.filesystem.root.input.areas.list import InputAreasList -from tests.storage.repository.filesystem.utils import TestMiddleNode, TestSubNode +from tests.storage.repository.filesystem.utils import CheckSubNode, TestMiddleNode -def build_tree() -> INode: +def build_tree() -> INode[t.Any, t.Any, t.Any]: config = Mock() config.path.exist.return_value = True config.zip_path = None @@ -19,14 +24,14 @@ def build_tree() -> INode: context=Mock(), config=config, children={ - "input": TestSubNode(value=100), - "output": TestSubNode(value=200), + "input": CheckSubNode(config, value=100), + "output": CheckSubNode(config, value=200), }, ) @pytest.mark.unit_test -def test_get(): +def test_get() -> None: tree = build_tree() res = tree.get(["input"]) @@ -37,7 +42,97 @@ def test_get(): @pytest.mark.unit_test -def test_get_depth(): +def test_get_input_areas_sets(tmp_path: Path) -> None: + """ + Read the content of the `sets.ini` file in the `input/areas` directory. + The goal of this test is to verify the behavior of the `get` method of the `FileStudyTree` class + for the case where the subdirectories or the INI file do not exist. + """ + + study_factory = StudyFactory(Mock(), Mock(), Mock()) + study_id = "c5633166-afe1-4ce5-9305-75bc2779aad6" + file_study = study_factory.create_from_fs(tmp_path, study_id, use_cache=False) + url = ["input", "areas", "sets"] # sets.ini + + # Empty study tree structure + actual = file_study.tree.get(url) + assert actual == {} + + # Add the "settings" directory + tmp_path.joinpath("input").mkdir() + actual = file_study.tree.get(url) + assert actual == {} + + # Add the "areas" directory + tmp_path.joinpath("input/areas").mkdir() + actual = file_study.tree.get(url) + assert actual == {} + + # Add the "sets.ini" file + sets = textwrap.dedent( + """\ + [all areas] + caption = All areas + comments = Spatial aggregates on all areas + output = false + apply-filter = add-all + """ + ) + tmp_path.joinpath("input/areas/sets.ini").write_text(sets) + actual = file_study.tree.get(url) + expected = { + "all areas": { + "caption": "All areas", + "comments": "Spatial aggregates on all areas", + "output": False, + "apply-filter": "add-all", + } + } + assert actual == expected + + +@pytest.mark.unit_test +def test_get_user_expansion_sensitivity_sensitivity_in(tmp_path: Path) -> None: + """ + Read the content of the `sensitivity_in.json` file in the `user/expansion/sensitivity` directory. + The goal of this test is to verify the behavior of the `get` method of the `FileStudyTree` class + for the case where the subdirectories or the JSON file do not exist. + """ + + study_factory = StudyFactory(Mock(), Mock(), Mock()) + study_id = "616ac707-c108-47af-9e02-c37cc043511a" + file_study = study_factory.create_from_fs(tmp_path, study_id, use_cache=False) + url = ["user", "expansion", "sensitivity", "sensitivity_in"] + + # Empty study tree structure + # fixme: bad error message + with pytest.raises(ChildNotFoundError, match=r"'expansion' not a child of User"): + file_study.tree.get(url) + + # Add the "user" directory + tmp_path.joinpath("user").mkdir() + with pytest.raises(ChildNotFoundError, match=r"'expansion' not a child of User"): + file_study.tree.get(url) + + # Add the "expansion" directory + tmp_path.joinpath("user/expansion").mkdir() + with pytest.raises(ChildNotFoundError, match=r"'sensitivity' not a child of Expansion"): + file_study.tree.get(url) + + # Add the "sensitivity" directory + tmp_path.joinpath("user/expansion/sensitivity").mkdir() + actual = file_study.tree.get(url) + assert actual == {} + + # Add the "sensitivity_in.json" file + sensitivity_obj = {"epsilon": 10000.0, "projection": ["pv", "battery"], "capex": True} + tmp_path.joinpath("user/expansion/sensitivity/sensitivity_in.json").write_text(json.dumps(sensitivity_obj)) + actual_obj = file_study.tree.get(url) + assert actual_obj == sensitivity_obj + + +@pytest.mark.unit_test +def test_get_depth() -> None: config = Mock() config.path.exist.return_value = True tree = TestMiddleNode( @@ -46,7 +141,7 @@ def test_get_depth(): children={"childA": build_tree(), "childB": build_tree()}, ) - expected = { + expected: t.Dict[str, t.Dict[str, t.Any]] = { "childA": {}, "childB": {}, } @@ -54,7 +149,7 @@ def test_get_depth(): assert tree.get(depth=1) == expected -def test_validate(): +def test_validate() -> None: config = Mock() config.path.exist.return_value = True tree = TestMiddleNode( @@ -77,7 +172,7 @@ def test_validate(): @pytest.mark.unit_test -def test_save(): +def test_save() -> None: tree = build_tree() tree.save(105, ["output"]) @@ -88,7 +183,7 @@ def test_save(): @pytest.mark.unit_test -def test_filter(): +def test_filter() -> None: tree = build_tree() expected_json = { @@ -100,7 +195,7 @@ def test_filter(): assert tree.get(["*", "value"]) == expected_json -def test_delete(tmp_path: Path): +def test_delete(tmp_path: Path) -> None: folder_node = tmp_path / "folder_node" folder_node.mkdir() sub_folder = folder_node / "sub_folder" @@ -124,7 +219,7 @@ def test_delete(tmp_path: Path): assert folder_node.exists() assert sub_folder.exists() - config = FileStudyTreeConfig(study_path=tmp_path, path=folder_node, study_id=-1, version=-1) + config = FileStudyTreeConfig(study_path=tmp_path, path=folder_node, study_id="-1", version=-1) tree_node = TestMiddleNode( context=Mock(), config=config, diff --git a/tests/storage/repository/filesystem/utils.py b/tests/storage/repository/filesystem/utils.py index 82e0107082..abef9e26e5 100644 --- a/tests/storage/repository/filesystem/utils.py +++ b/tests/storage/repository/filesystem/utils.py @@ -8,7 +8,7 @@ from antarest.study.storage.rawstudy.model.filesystem.inode import TREE, INode -class TestSubNode(INode[int, int, int]): +class CheckSubNode(INode[int, int, int]): def normalize(self) -> None: pass @@ -18,7 +18,8 @@ def denormalize(self) -> None: def build(self, config: FileStudyTreeConfig) -> "TREE": pass - def __init__(self, value: int): + def __init__(self, config: FileStudyTreeConfig, value: int): + super().__init__(config) self.value = value def get_node( diff --git a/tests/storage/repository/test_study.py b/tests/storage/repository/test_study.py index f865ab613a..7aa5fb23cd 100644 --- a/tests/storage/repository/test_study.py +++ b/tests/storage/repository/test_study.py @@ -1,22 +1,25 @@ +import json from datetime import datetime +from sqlalchemy.orm import Session # type: ignore + from antarest.core.cache.business.local_chache import LocalCache from antarest.core.model import PublicMode from antarest.login.model import Group, User -from antarest.study.model import DEFAULT_WORKSPACE_NAME, RawStudy, Study, StudyContentStatus -from antarest.study.repository import StudyMetadataRepository +from antarest.study.model import DEFAULT_WORKSPACE_NAME, RawStudy, Study, StudyAdditionalData, StudyContentStatus +from antarest.study.repository import AccessPermissions, StudyFilter, StudyMetadataRepository from antarest.study.storage.variantstudy.model.dbmodel import VariantStudy -from tests.helpers import with_db_context -@with_db_context -def test_lifecycle() -> None: - user = User(id=0, name="admin") +def test_lifecycle(db_session: Session) -> None: + repo = StudyMetadataRepository(LocalCache(), session=db_session) + + user = User(id=1, name="admin") group = Group(id="my-group", name="group") - repo = StudyMetadataRepository(LocalCache()) + a = Study( name="a", - version="42", + version="820", author="John Smith", created_at=datetime.utcnow(), updated_at=datetime.utcnow(), @@ -26,7 +29,7 @@ def test_lifecycle() -> None: ) b = RawStudy( name="b", - version="43", + version="830", author="Morpheus", created_at=datetime.utcnow(), updated_at=datetime.utcnow(), @@ -36,7 +39,7 @@ def test_lifecycle() -> None: ) c = RawStudy( name="c", - version="43", + version="830", author="Trinity", created_at=datetime.utcnow(), updated_at=datetime.utcnow(), @@ -47,7 +50,7 @@ def test_lifecycle() -> None: ) d = VariantStudy( name="d", - version="43", + version="830", author="Mr. Anderson", created_at=datetime.utcnow(), updated_at=datetime.utcnow(), @@ -57,30 +60,75 @@ def test_lifecycle() -> None: ) a = repo.save(a) - b = repo.save(b) + a_id = a.id + + repo.save(b) repo.save(c) repo.save(d) - assert b.id - c = repo.one(a.id) - assert a == c - assert len(repo.get_all()) == 4 + c = repo.one(a_id) + assert a_id == c.id + + assert len(repo.get_all(study_filter=StudyFilter(access_permissions=AccessPermissions(is_admin=True)))) == 4 assert len(repo.get_all_raw(exists=True)) == 1 assert len(repo.get_all_raw(exists=False)) == 1 assert len(repo.get_all_raw()) == 2 - repo.delete(a.id) - assert repo.get(a.id) is None + repo.delete(a_id) + assert repo.get(a_id) is None + + +def test_study__additional_data(db_session: Session) -> None: + repo = StudyMetadataRepository(LocalCache(), session=db_session) + + user = User(id=0, name="admin") + group = Group(id="my-group", name="group") + + patch = {"foo": "bar"} + a = RawStudy( + name="a", + version="820", + author="John Smith", + created_at=datetime.utcnow(), + updated_at=datetime.utcnow(), + public_mode=PublicMode.FULL, + owner=user, + groups=[group], + workspace=DEFAULT_WORKSPACE_NAME, + path="study", + content_status=StudyContentStatus.WARNING, + additional_data=StudyAdditionalData(author="John Smith", horizon="2024-2050", patch=json.dumps(patch)), + ) + + repo.save(a) + a_id = a.id + + # Check that the additional data is correctly saved + additional_data = repo.get_additional_data(a_id) + assert additional_data.author == "John Smith" + assert additional_data.horizon == "2024-2050" + assert json.loads(additional_data.patch) == patch + + # Check that the additional data is correctly updated + new_patch = {"foo": "baz"} + a.additional_data.patch = json.dumps(new_patch) + repo.save(a) + additional_data = repo.get_additional_data(a_id) + assert json.loads(additional_data.patch) == new_patch + + # Check that the additional data is correctly deleted when the study is deleted + repo.delete(a_id) + assert repo.get_additional_data(a_id) is None + +def test_study_inheritance(db_session: Session) -> None: + repo = StudyMetadataRepository(LocalCache(), session=db_session) -@with_db_context -def test_study_inheritance() -> None: user = User(id=0, name="admin") group = Group(id="my-group", name="group") - repo = StudyMetadataRepository(LocalCache()) a = RawStudy( name="a", - version="42", + version="820", author="John Smith", created_at=datetime.utcnow(), updated_at=datetime.utcnow(), diff --git a/tests/storage/study_upgrader/test_upgrade_870.py b/tests/storage/study_upgrader/test_upgrade_870.py new file mode 100644 index 0000000000..f22a7a30ef --- /dev/null +++ b/tests/storage/study_upgrader/test_upgrade_870.py @@ -0,0 +1,31 @@ +from antarest.study.storage.study_upgrader import upgrade_870 +from tests.storage.business.test_study_version_upgrader import are_same_dir +from tests.storage.study_upgrader.conftest import StudyAssets + + +def test_nominal_case(study_assets: StudyAssets): + """ + Check that binding constraints and thermal folders are correctly modified + """ + + # upgrade the study + upgrade_870(study_assets.study_dir) + + # compare input folders (bindings + thermals) + actual_input_path = study_assets.study_dir.joinpath("input") + expected_input_path = study_assets.expected_dir.joinpath("input") + assert are_same_dir(actual_input_path, expected_input_path) + + +def test_empty_binding_constraints(study_assets: StudyAssets): + """ + Check that binding constraints and thermal folders are correctly modified + """ + + # upgrade the study + upgrade_870(study_assets.study_dir) + + # compare input folders (bindings + thermals) + actual_input_path = study_assets.study_dir.joinpath("input") + expected_input_path = study_assets.expected_dir.joinpath("input") + assert are_same_dir(actual_input_path, expected_input_path) diff --git a/tests/storage/study_upgrader/test_upgrade_880.py b/tests/storage/study_upgrader/test_upgrade_880.py new file mode 100644 index 0000000000..36dfa7dcc6 --- /dev/null +++ b/tests/storage/study_upgrader/test_upgrade_880.py @@ -0,0 +1,17 @@ +from antarest.study.storage.study_upgrader import upgrade_880 +from tests.storage.business.test_study_version_upgrader import are_same_dir +from tests.storage.study_upgrader.conftest import StudyAssets + + +def test_nominal_case(study_assets: StudyAssets): + """ + Check that short term storages are correctly modified + """ + + # upgrade the study + upgrade_880(study_assets.study_dir) + + # compare st-storage folders (st-storage) + actual_input_path = study_assets.study_dir / "input" / "st-storage" + expected_input_path = study_assets.expected_dir / "input" / "st-storage" + assert are_same_dir(actual_input_path, expected_input_path) diff --git a/tests/storage/study_upgrader/upgrade_870/empty_binding_constraints/little_study_860.expected.zip b/tests/storage/study_upgrader/upgrade_870/empty_binding_constraints/little_study_860.expected.zip new file mode 100644 index 0000000000..f78b95bcfe Binary files /dev/null and b/tests/storage/study_upgrader/upgrade_870/empty_binding_constraints/little_study_860.expected.zip differ diff --git a/tests/storage/study_upgrader/upgrade_870/empty_binding_constraints/little_study_860.zip b/tests/storage/study_upgrader/upgrade_870/empty_binding_constraints/little_study_860.zip new file mode 100644 index 0000000000..ecc496b084 Binary files /dev/null and b/tests/storage/study_upgrader/upgrade_870/empty_binding_constraints/little_study_860.zip differ diff --git a/tests/storage/study_upgrader/upgrade_870/nominal_case/little_study_860.expected.zip b/tests/storage/study_upgrader/upgrade_870/nominal_case/little_study_860.expected.zip new file mode 100644 index 0000000000..bb83d77745 Binary files /dev/null and b/tests/storage/study_upgrader/upgrade_870/nominal_case/little_study_860.expected.zip differ diff --git a/tests/storage/study_upgrader/upgrade_870/nominal_case/little_study_860.zip b/tests/storage/study_upgrader/upgrade_870/nominal_case/little_study_860.zip new file mode 100644 index 0000000000..ee4aef0d34 Binary files /dev/null and b/tests/storage/study_upgrader/upgrade_870/nominal_case/little_study_860.zip differ diff --git a/tests/storage/study_upgrader/upgrade_880/nominal_case/little_study_870.expected.zip b/tests/storage/study_upgrader/upgrade_880/nominal_case/little_study_870.expected.zip new file mode 100644 index 0000000000..ddeb10ad18 Binary files /dev/null and b/tests/storage/study_upgrader/upgrade_880/nominal_case/little_study_870.expected.zip differ diff --git a/tests/storage/study_upgrader/upgrade_880/nominal_case/little_study_870.zip b/tests/storage/study_upgrader/upgrade_880/nominal_case/little_study_870.zip new file mode 100644 index 0000000000..88aa7533c3 Binary files /dev/null and b/tests/storage/study_upgrader/upgrade_880/nominal_case/little_study_870.zip differ diff --git a/tests/storage/test_service.py b/tests/storage/test_service.py index e7e8662394..c322b69672 100644 --- a/tests/storage/test_service.py +++ b/tests/storage/test_service.py @@ -44,7 +44,7 @@ TimeSerie, TimeSeriesData, ) -from antarest.study.repository import StudyFilter, StudyMetadataRepository +from antarest.study.repository import AccessPermissions, StudyFilter, StudyMetadataRepository from antarest.study.service import MAX_MISSING_STUDY_TIMEOUT, StudyService, StudyUpgraderTask, UserHasNotPermissionError from antarest.study.storage.patch_service import PatchService from antarest.study.storage.rawstudy.model.filesystem.config.model import ( @@ -172,6 +172,7 @@ def test_study_listing(db_session: Session) -> None: config = Config(storage=StorageConfig(workspaces={DEFAULT_WORKSPACE_NAME: WorkspaceConfig()})) repository = StudyMetadataRepository(cache_service=Mock(spec=ICache), session=db_session) service = build_study_service(raw_study_service, repository, config, cache_service=cache) + params: RequestParameters = RequestParameters(user=JWTUser(id=2, impersonator=2, type="users")) # retrieve studies that are not managed # use the db recorder to check that: @@ -179,10 +180,7 @@ def test_study_listing(db_session: Session) -> None: # 2- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: studies = service.get_studies_information( - study_filter=StudyFilter( - managed=False, - ), - params=RequestParameters(user=JWTUser(id=2, impersonator=2, type="users")), + study_filter=StudyFilter(managed=False, access_permissions=AccessPermissions.from_params(params)), ) assert len(db_recorder.sql_statements) == 1, str(db_recorder) @@ -196,10 +194,7 @@ def test_study_listing(db_session: Session) -> None: # 2- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: studies = service.get_studies_information( - study_filter=StudyFilter( - managed=True, - ), - params=RequestParameters(user=JWTUser(id=2, impersonator=2, type="users")), + study_filter=StudyFilter(managed=True, access_permissions=AccessPermissions.from_params(params)), ) assert len(db_recorder.sql_statements) == 1, str(db_recorder) @@ -213,10 +208,7 @@ def test_study_listing(db_session: Session) -> None: # 2- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: studies = service.get_studies_information( - study_filter=StudyFilter( - managed=None, - ), - params=RequestParameters(user=JWTUser(id=2, impersonator=2, type="users")), + study_filter=StudyFilter(managed=None, access_permissions=AccessPermissions.from_params(params)), ) assert len(db_recorder.sql_statements) == 1, str(db_recorder) @@ -230,10 +222,7 @@ def test_study_listing(db_session: Session) -> None: # 2- the `put` method of `cache` was never used with DBStatementRecorder(db_session.bind) as db_recorder: studies = service.get_studies_information( - study_filter=StudyFilter( - managed=None, - ), - params=RequestParameters(user=JWTUser(id=2, impersonator=2, type="users")), + study_filter=StudyFilter(managed=None, access_permissions=AccessPermissions.from_params(params)), ) assert len(db_recorder.sql_statements) == 1, str(db_recorder) with contextlib.suppress(AssertionError): @@ -350,18 +339,30 @@ def test_partial_sync_studies_from_disk() -> None: ) -@pytest.mark.unit_test -def test_remove_duplicate() -> None: - ma = RawStudy(id="a", path="a") - mb = RawStudy(id="b", path="a") +@with_db_context +def test_remove_duplicate(db_session: Session) -> None: + with db_session: + db_session.add(RawStudy(id="a", path="/path/to/a")) + db_session.add(RawStudy(id="b", path="/path/to/a")) + db_session.add(RawStudy(id="c", path="/path/to/c")) + db_session.commit() + study_count = db_session.query(RawStudy).filter(RawStudy.path == "/path/to/a").count() + assert study_count == 2 # there are 2 studies with same path before removing duplicates - repository = Mock() - repository.get_all.return_value = [ma, mb] - config = Config(storage=StorageConfig(workspaces={DEFAULT_WORKSPACE_NAME: WorkspaceConfig()})) - service = build_study_service(Mock(), repository, config) + with db_session: + repository = StudyMetadataRepository(Mock(), db_session) + config = Config(storage=StorageConfig(workspaces={DEFAULT_WORKSPACE_NAME: WorkspaceConfig()})) + service = build_study_service(Mock(), repository, config) + service.remove_duplicates() - service.remove_duplicates() - repository.delete.assert_called_once_with(mb.id) + # example with 1 duplicate with same path + with db_session: + study_count = db_session.query(RawStudy).filter(RawStudy.path == "/path/to/a").count() + assert study_count == 1 + # example with no duplicates with same path + with db_session: + study_count = db_session.query(RawStudy).filter(RawStudy.path == "/path/to/c").count() + assert study_count == 1 # noinspection PyArgumentList @@ -571,7 +572,7 @@ def test_download_output() -> None: # AREA TYPE res_matrix = MatrixAggregationResultDTO( index=MatrixIndex( - start_date="2001-01-01 00:00:00", + start_date="2018-01-01 00:00:00", steps=1, first_week_size=7, level=StudyDownloadLevelDTO.ANNUAL, @@ -631,7 +632,7 @@ def test_download_output() -> None: input_data.filter = ["east>west"] res_matrix = MatrixAggregationResultDTO( index=MatrixIndex( - start_date="2001-01-01 00:00:00", + start_date="2018-01-01 00:00:00", steps=1, first_week_size=7, level=StudyDownloadLevelDTO.ANNUAL, @@ -661,7 +662,7 @@ def test_download_output() -> None: input_data.filterIn = "n" res_matrix = MatrixAggregationResultDTO( index=MatrixIndex( - start_date="2001-01-01 00:00:00", + start_date="2018-01-01 00:00:00", steps=1, first_week_size=7, level=StudyDownloadLevelDTO.ANNUAL, diff --git a/tests/study/business/areas/test_st_storage_management.py b/tests/study/business/areas/test_st_storage_management.py index 5c3e7e660c..74089bc7cd 100644 --- a/tests/study/business/areas/test_st_storage_management.py +++ b/tests/study/business/areas/test_st_storage_management.py @@ -1,8 +1,8 @@ import datetime import io import re +import typing as t import uuid -from typing import Any, MutableMapping, Sequence, cast from unittest.mock import Mock import numpy as np @@ -10,20 +10,14 @@ from pydantic import ValidationError from sqlalchemy.orm.session import Session # type: ignore -from antarest.core.exceptions import ( - AreaNotFound, - STStorageConfigNotFoundError, - STStorageFieldsNotFoundError, - STStorageMatrixNotFoundError, - STStorageNotFoundError, -) +from antarest.core.exceptions import AreaNotFound, STStorageConfigNotFound, STStorageMatrixNotFound, STStorageNotFound from antarest.core.model import PublicMode from antarest.login.model import Group, User from antarest.study.business.areas.st_storage_management import STStorageInput, STStorageManager from antarest.study.model import RawStudy, Study, StudyContentStatus from antarest.study.storage.rawstudy.ini_reader import IniReader -from antarest.study.storage.rawstudy.model.filesystem.config.model import Area, FileStudyTreeConfig -from antarest.study.storage.rawstudy.model.filesystem.config.st_storage import STStorageConfig, STStorageGroup +from antarest.study.storage.rawstudy.model.filesystem.config.model import FileStudyTreeConfig +from antarest.study.storage.rawstudy.model.filesystem.config.st_storage import STStorageGroup from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy from antarest.study.storage.rawstudy.model.filesystem.ini_file_node import IniFileNode from antarest.study.storage.rawstudy.model.filesystem.root.filestudytree import FileStudyTree @@ -65,6 +59,11 @@ LIST_CFG = IniReader().read(io.StringIO(LIST_INI)) +ALL_STORAGES = { + "west": {"list": LIST_CFG}, + "east": {"list": {}}, +} + class TestSTStorageManager: @pytest.fixture(name="study_storage_service") @@ -103,7 +102,114 @@ def study_uuid_fixture(self, db_session: Session) -> str: ) db_session.add(raw_study) db_session.commit() - return cast(str, raw_study.id) + return t.cast(str, raw_study.id) + + def test_get_all_storages__nominal_case( + self, + db_session: Session, + study_storage_service: StudyStorageService, + study_uuid: str, + ) -> None: + """ + This unit test is to verify the behavior of the `get_all_storages` + method in the `STStorageManager` class under nominal conditions. + It checks whether the method returns the expected storage lists + for each area, based on a specific configuration. + """ + # The study must be fetched from the database + study: RawStudy = db_session.query(Study).get(study_uuid) + + # Prepare the mocks + storage = study_storage_service.get_storage(study) + file_study = storage.get_raw(study) + file_study.tree = Mock( + spec=FileStudyTree, + get=Mock(return_value=ALL_STORAGES), + ) + + # Given the following arguments + manager = STStorageManager(study_storage_service) + + # run + all_storages = manager.get_all_storages_props(study) + + # Check + actual = { + area_id: [form.dict(by_alias=True) for form in clusters_by_ids.values()] + for area_id, clusters_by_ids in all_storages.items() + } + expected = { + "west": [ + { + "id": "storage1", + "enabled": None, + "group": STStorageGroup.BATTERY, + "name": "Storage1", + "injectionNominalCapacity": 1500.0, + "withdrawalNominalCapacity": 1500.0, + "reservoirCapacity": 20000.0, + "efficiency": 0.94, + "initialLevel": 0.5, + "initialLevelOptim": True, + }, + { + "id": "storage2", + "enabled": None, + "group": STStorageGroup.PSP_CLOSED, + "name": "Storage2", + "injectionNominalCapacity": 2000.0, + "withdrawalNominalCapacity": 1500.0, + "reservoirCapacity": 20000.0, + "efficiency": 0.78, + "initialLevel": 0.5, + "initialLevelOptim": False, + }, + { + "id": "storage3", + "enabled": None, + "group": STStorageGroup.PSP_CLOSED, + "name": "Storage3", + "injectionNominalCapacity": 1500.0, + "withdrawalNominalCapacity": 1500.0, + "reservoirCapacity": 21000.0, + "efficiency": 0.72, + "initialLevel": 1.0, + "initialLevelOptim": False, + }, + ], + } + assert actual == expected + + def test_get_all_storages__config_not_found( + self, + db_session: Session, + study_storage_service: StudyStorageService, + study_uuid: str, + ) -> None: + """ + This test verifies that when the `get_all_storages` method is called + with a study and the corresponding configuration is not found + (indicated by the `KeyError` raised by the mock), it correctly + raises the `STStorageConfigNotFound` exception with the expected error + message containing the study ID. + """ + # The study must be fetched from the database + study: RawStudy = db_session.query(Study).get(study_uuid) + + # Prepare the mocks + storage = study_storage_service.get_storage(study) + file_study = storage.get_raw(study) + file_study.tree = Mock( + spec=FileStudyTree, + get=Mock(side_effect=KeyError("Oops!")), + ) + + # Given the following arguments + manager = STStorageManager(study_storage_service) + + # run + with pytest.raises(STStorageConfigNotFound, match="not found"): + manager.get_all_storages_props(study) def test_get_st_storages__nominal_case( self, @@ -147,6 +253,7 @@ def test_get_st_storages__nominal_case( "name": "Storage1", "reservoirCapacity": 20000.0, "withdrawalNominalCapacity": 1500.0, + "enabled": None, }, { "efficiency": 0.78, @@ -158,6 +265,7 @@ def test_get_st_storages__nominal_case( "name": "Storage2", "reservoirCapacity": 20000.0, "withdrawalNominalCapacity": 1500.0, + "enabled": None, }, { "efficiency": 0.72, @@ -169,6 +277,7 @@ def test_get_st_storages__nominal_case( "name": "Storage3", "reservoirCapacity": 21000.0, "withdrawalNominalCapacity": 1500.0, + "enabled": None, }, ] assert actual == expected @@ -183,7 +292,7 @@ def test_get_st_storages__config_not_found( This test verifies that when the `get_storages` method is called with a study and area ID, and the corresponding configuration is not found (indicated by the `KeyError` raised by the mock), it correctly - raises the `STStorageConfigNotFoundError` exception with the expected error + raises the `STStorageConfigNotFound` exception with the expected error message containing the study ID and area ID. """ # The study must be fetched from the database @@ -201,7 +310,7 @@ def test_get_st_storages__config_not_found( manager = STStorageManager(study_storage_service) # run - with pytest.raises(STStorageConfigNotFoundError, match="not found") as ctx: + with pytest.raises(STStorageConfigNotFound, match="not found") as ctx: manager.get_storages(study, area_id="West") # ensure the error message contains at least the study ID and area ID @@ -255,6 +364,7 @@ def test_get_st_storage__nominal_case( "name": "Storage1", "reservoirCapacity": 20000.0, "withdrawalNominalCapacity": 1500.0, + "enabled": None, } assert actual == expected @@ -286,11 +396,10 @@ def test_update_storage__nominal_case( ini_file_node = IniFileNode(context=Mock(), config=Mock()) file_study.tree = Mock( spec=FileStudyTree, - get=Mock(return_value=LIST_CFG["storage1"]), + get=Mock(return_value=LIST_CFG), get_node=Mock(return_value=ini_file_node), ) - area = Mock(spec=Area) mock_config = Mock(spec=FileStudyTreeConfig, study_id=study.id) file_study.config = mock_config @@ -299,20 +408,22 @@ def test_update_storage__nominal_case( edit_form = STStorageInput(initial_level=0, initial_level_optim=False) # Test behavior for area not in study - mock_config.areas = {"fake_area": area} - with pytest.raises(AreaNotFound) as ctx: - manager.update_storage(study, area_id="West", storage_id="storage1", form=edit_form) - assert ctx.value.detail == "Area is not found: 'West'" + # noinspection PyTypeChecker + file_study.tree.get.return_value = {} + with pytest.raises((AreaNotFound, STStorageNotFound)) as ctx: + manager.update_storage(study, area_id="unknown_area", storage_id="storage1", form=edit_form) + assert "unknown_area" in ctx.value.detail + assert "storage1" in ctx.value.detail # Test behavior for st_storage not in study - mock_config.areas = {"West": area} - area.st_storages = [STStorageConfig(name="fake_name", group="battery")] - with pytest.raises(STStorageNotFoundError) as ctx: - manager.update_storage(study, area_id="West", storage_id="storage1", form=edit_form) - assert ctx.value.detail == "Short-term storage 'storage1' not found in area 'West'" + file_study.tree.get.return_value = {"storage1": LIST_CFG["storage1"]} + with pytest.raises(STStorageNotFound) as ctx: + manager.update_storage(study, area_id="West", storage_id="unknown_storage", form=edit_form) + assert "West" in ctx.value.detail + assert "unknown_storage" in ctx.value.detail # Test behavior for nominal case - area.st_storages = [STStorageConfig(name="storage1", group="battery")] + file_study.tree.get.return_value = LIST_CFG manager.update_storage(study, area_id="West", storage_id="storage1", form=edit_form) # Assert that the storage fields have been updated @@ -351,7 +462,7 @@ def test_get_st_storage__config_not_found( """ Test the `get_st_storage` method of the `STStorageManager` class when the configuration is not found. - This test verifies that the `get_st_storage` method raises an `STStorageFieldsNotFoundError` + This test verifies that the `get_st_storage` method raises an `STStorageNotFound` exception when the configuration for the provided study, area, and storage ID combination is not found. Args: @@ -375,7 +486,7 @@ def test_get_st_storage__config_not_found( manager = STStorageManager(study_storage_service) # Run the method being tested and expect an exception - with pytest.raises(STStorageFieldsNotFoundError, match="not found") as ctx: + with pytest.raises(STStorageNotFound, match="not found") as ctx: manager.get_storage(study, area_id="West", storage_id="storage1") # ensure the error message contains at least the study ID, area ID and storage ID err_msg = str(ctx.value) @@ -436,7 +547,7 @@ def test_get_matrix__config_not_found( """ Test the `get_matrix` method of the `STStorageManager` class when the time series is not found. - This test verifies that the `get_matrix` method raises an `STStorageFieldsNotFoundError` + This test verifies that the `get_matrix` method raises an `STStorageNotFound` exception when the configuration for the provided study, area, time series, and storage ID combination is not found. @@ -461,7 +572,7 @@ def test_get_matrix__config_not_found( manager = STStorageManager(study_storage_service) # Run the method being tested and expect an exception - with pytest.raises(STStorageMatrixNotFoundError, match="not found") as ctx: + with pytest.raises(STStorageMatrixNotFound, match="not found") as ctx: manager.get_matrix(study, area_id="West", storage_id="storage1", ts_name="inflows") # ensure the error message contains at least the study ID, area ID and storage ID err_msg = str(ctx.value) @@ -477,7 +588,7 @@ def test_get_matrix__invalid_matrix( """ Test the `get_matrix` method of the `STStorageManager` class when the time series is not found. - This test verifies that the `get_matrix` method raises an `STStorageFieldsNotFoundError` + This test verifies that the `get_matrix` method raises an `STStorageNotFound` exception when the configuration for the provided study, area, time series, and storage ID combination is not found. @@ -534,7 +645,7 @@ def test_validate_matrices__nominal( } # Prepare the mocks - def tree_get(url: Sequence[str], **_: Any) -> MutableMapping[str, Any]: + def tree_get(url: t.Sequence[str], **_: t.Any) -> t.MutableMapping[str, t.Any]: name = url[-1] array = matrices[name] return { @@ -571,7 +682,7 @@ def test_validate_matrices__out_of_bound( } # Prepare the mocks - def tree_get(url: Sequence[str], **_: Any) -> MutableMapping[str, Any]: + def tree_get(url: t.Sequence[str], **_: t.Any) -> t.MutableMapping[str, t.Any]: name = url[-1] array = matrices[name] return { @@ -637,7 +748,7 @@ def test_validate_matrices__rule_curve( } # Prepare the mocks - def tree_get(url: Sequence[str], **_: Any) -> MutableMapping[str, Any]: + def tree_get(url: t.Sequence[str], **_: t.Any) -> t.MutableMapping[str, t.Any]: name = url[-1] array = matrices[name] return { diff --git a/tests/study/business/areas/test_thermal_management.py b/tests/study/business/areas/test_thermal_management.py index a0f7183542..dd52ec9538 100644 --- a/tests/study/business/areas/test_thermal_management.py +++ b/tests/study/business/areas/test_thermal_management.py @@ -23,6 +23,34 @@ from tests.study.business.areas.assets import ASSETS_DIR +class TestThermalClusterGroup: + """ + Tests for the `ThermalClusterGroup` enumeration. + """ + + def test_nominal_case(self): + """ + When a group is read from a INI file, the group should be the same as the one in the file. + """ + group = ThermalClusterGroup("gas") # different case: original is "Gas" + assert group == ThermalClusterGroup.GAS + + def test_unknown(self): + """ + When an unknown group is read from a INI file, the group should be `OTHER1`. + Note that this is the current behavior in Antares Solver. + """ + group = ThermalClusterGroup("unknown") + assert group == ThermalClusterGroup.OTHER1 + + def test_invalid_type(self): + """ + When an invalid type is used to create a group, a `ValueError` should be raised. + """ + with pytest.raises(ValueError): + ThermalClusterGroup(123) + + @pytest.fixture(name="zip_legacy_path") def zip_legacy_path_fixture(tmp_path: Path) -> Path: target_dir = tmp_path.joinpath("resources") @@ -141,6 +169,10 @@ def test_get_cluster__study_legacy( "op3": None, "op4": None, "op5": None, + # These values are also None as they are defined in v8.7+ + "costGeneration": None, + "efficiency": None, + "variableOMCost": None, } assert actual == expected @@ -203,6 +235,9 @@ def test_get_clusters__study_legacy( "op3": None, "op4": None, "op5": None, + "costGeneration": None, + "efficiency": None, + "variableOMCost": None, }, { "id": "on and must 2", @@ -239,6 +274,9 @@ def test_get_clusters__study_legacy( "op3": None, "op4": None, "op5": None, + "costGeneration": None, + "efficiency": None, + "variableOMCost": None, }, { "id": "2 avail and must 2", @@ -275,6 +313,9 @@ def test_get_clusters__study_legacy( "op3": None, "op4": None, "op5": None, + "costGeneration": None, + "efficiency": None, + "variableOMCost": None, }, ] assert actual == expected @@ -343,6 +384,9 @@ def test_create_cluster__study_legacy( "pm25": None, "pm5": None, "so2": None, + "costGeneration": None, + "efficiency": None, + "variableOMCost": None, "spinning": 0.0, "spreadCost": 0.0, "startupCost": 0.0, @@ -407,6 +451,10 @@ def test_update_cluster( "op3": None, "op4": None, "op5": None, + # These values are also None as they are defined in v8.7+ + "costGeneration": None, + "efficiency": None, + "variableOMCost": None, } assert actual == expected diff --git a/tests/study/business/test_all_optional_metaclass.py b/tests/study/business/test_all_optional_metaclass.py index 2e83a4e433..1c379f6460 100644 --- a/tests/study/business/test_all_optional_metaclass.py +++ b/tests/study/business/test_all_optional_metaclass.py @@ -3,7 +3,7 @@ import pytest from pydantic import BaseModel, Field, ValidationError -from antarest.study.business.utils import AllOptionalMetaclass +from antarest.study.business.all_optional_meta import AllOptionalMetaclass # ============================================== # Classic way to use default and optional values diff --git a/tests/study/business/test_binding_constraint_management.py b/tests/study/business/test_binding_constraint_management.py new file mode 100644 index 0000000000..17bf1628ec --- /dev/null +++ b/tests/study/business/test_binding_constraint_management.py @@ -0,0 +1,204 @@ +import typing as t + +import pytest + +from antarest.study.business.binding_constraint_management import ( + ClusterTerm, + ConstraintFilters, + ConstraintOutput, + ConstraintOutput870, + ConstraintOutputBase, + ConstraintTerm, + LinkTerm, +) + + +class TestConstraintFilter: + def test_init(self) -> None: + bc_filter = ConstraintFilters() + assert not bc_filter.bc_id + assert not bc_filter.enabled + assert not bc_filter.operator + assert not bc_filter.comments + assert not bc_filter.group + assert not bc_filter.time_step + assert not bc_filter.area_name + assert not bc_filter.cluster_name + assert not bc_filter.link_id + assert not bc_filter.cluster_id + + @pytest.mark.parametrize("bc_id, expected", [("bc1", True), ("BC1", False), ("bc2", False), ("", True)]) + @pytest.mark.parametrize("cls", [ConstraintOutputBase, ConstraintOutput870]) + def test_filter_by__bc_id(self, bc_id: str, expected: bool, cls: t.Type[ConstraintOutput]) -> None: + """ + The filter should match if the `bc_id` is equal to the constraint's `bc_id` or if the filter is empty. + Comparisons should be case-sensitive. + """ + bc_filter = ConstraintFilters(bc_id=bc_id) + constraint = cls(id="bc1", name="BC1") + assert bc_filter.match_filters(constraint) == expected, "" + + @pytest.mark.parametrize("enabled, expected", [(True, True), (False, False), (None, True)]) + @pytest.mark.parametrize("cls", [ConstraintOutputBase, ConstraintOutput870]) + def test_filter_by__enabled(self, enabled: t.Optional[bool], expected: bool, cls: t.Type[ConstraintOutput]) -> None: + """ + The filter should match if the `enabled` is equal to the constraint's `enabled` or if the filter is empty. + """ + bc_filter = ConstraintFilters(enabled=enabled) + constraint = cls(id="bc1", name="BC1") + assert bc_filter.match_filters(constraint) == expected + + @pytest.mark.parametrize("operator, expected", [("equal", True), ("both", False), (None, True)]) + @pytest.mark.parametrize("cls", [ConstraintOutputBase, ConstraintOutput870]) + def test_filter_by__operator(self, operator: str, expected: bool, cls: t.Type[ConstraintOutput]) -> None: + """ + The filter should match if the `operator` is equal to the constraint's `operator` or if the filter is empty. + """ + bc_filter = ConstraintFilters(operator=operator) + constraint = cls(id="bc1", name="BC1", operator="equal") + assert bc_filter.match_filters(constraint) == expected + + @pytest.mark.parametrize("comments, expected", [("hello", True), ("HELLO", True), ("goodbye", False), ("", True)]) + @pytest.mark.parametrize("cls", [ConstraintOutputBase, ConstraintOutput870]) + def test_filter_by__comments(self, comments: str, expected: bool, cls: t.Type[ConstraintOutput]) -> None: + """ + The filter should match if the constraint's `comments` contains the filter's `comments` or if the filter is empty. + Comparisons should be case-insensitive. + """ + bc_filter = ConstraintFilters(comments=comments) + constraint = cls(id="bc1", name="BC1", comments="Say hello!") + assert bc_filter.match_filters(constraint) == expected + + @pytest.mark.parametrize("group, expected", [("grp1", False), ("grp2", False), ("", True)]) + @pytest.mark.parametrize("cls", [ConstraintOutput]) + def test_filter_by__group(self, group: str, expected: bool, cls: t.Type[ConstraintOutput]) -> None: + """ + The filter should never match if the filter's `group` is not empty. + """ + bc_filter = ConstraintFilters(group=group) + constraint = cls(id="bc1", name="BC1") + assert bc_filter.match_filters(constraint) == expected + + @pytest.mark.parametrize("group, expected", [("grp1", True), ("GRP1", True), ("grp2", False), ("", True)]) + @pytest.mark.parametrize("cls", [ConstraintOutput870]) + def test_filter_by__group(self, group: str, expected: bool, cls: t.Type[ConstraintOutput870]) -> None: + """ + The filter should match if the `group` is equal to the constraint's `group` or if the filter is empty. + Comparisons should be case-insensitive. + """ + bc_filter = ConstraintFilters(group=group) + constraint = cls(id="bc1", name="BC1", group="Grp1") + assert bc_filter.match_filters(constraint) == expected + + @pytest.mark.parametrize("time_step, expected", [("hourly", True), ("daily", False), (None, True)]) + @pytest.mark.parametrize("cls", [ConstraintOutputBase, ConstraintOutput870]) + def test_filter_by__time_step(self, time_step: str, expected: bool, cls: t.Type[ConstraintOutput]) -> None: + """ + The filter should match if the `time_step` is hourly to the constraint's `time_step` or if the filter is empty. + """ + bc_filter = ConstraintFilters(time_step=time_step) + constraint = cls(id="bc1", name="BC1", time_step="hourly") + assert bc_filter.match_filters(constraint) == expected + + @pytest.mark.parametrize( + "area_name, expected", + [("FR", True), ("fr", True), ("DE", True), ("IT", True), ("HU", True), ("EN", False), ("", True)], + ) + @pytest.mark.parametrize("cls", [ConstraintOutputBase, ConstraintOutput870]) + def test_filter_by__area_name(self, area_name: str, expected: bool, cls: t.Type[ConstraintOutput]) -> None: + """ + The filter should match if one of the constraint's terms has an area name which contains + the filter's area name or if the filter is empty. + Comparisons should be case-insensitive. + """ + bc_filter = ConstraintFilters(area_name=area_name) + constraint = cls(id="bc1", name="BC1") + constraint.terms.extend( + [ + ConstraintTerm(weight=2.0, offset=5, data=LinkTerm(area1="area_FR_x", area2="area_DE_x")), + ConstraintTerm(weight=3.0, offset=5, data=LinkTerm(area1="area_IT_y", area2="area_DE_y")), + ConstraintTerm(weight=2.0, offset=5, data=ClusterTerm(area="area_HU_z", cluster="area_CL1_z")), + ] + ) + assert bc_filter.match_filters(constraint) == expected + + @pytest.mark.parametrize( + "cluster_name, expected", + [("cl1", True), ("CL1", True), ("cl2", False), ("", True)], + ) + @pytest.mark.parametrize("cls", [ConstraintOutputBase, ConstraintOutput870]) + def test_filter_by__cluster_name(self, cluster_name: str, expected: bool, cls: t.Type[ConstraintOutput]) -> None: + """ + The filter should match if one of the constraint's terms has a cluster name which contains + the filter's cluster name or if the filter is empty. + Comparisons should be case-insensitive. + """ + bc_filter = ConstraintFilters(cluster_name=cluster_name) + constraint = cls(id="bc1", name="BC1") + constraint.terms.extend( + [ + ConstraintTerm(weight=2.0, offset=5, data=LinkTerm(area1="area_FR_x", area2="area_DE_x")), + ConstraintTerm(weight=3.0, offset=5, data=LinkTerm(area1="area_IT_y", area2="area_DE_y")), + ConstraintTerm(weight=2.0, offset=5, data=ClusterTerm(area="area_HU_z", cluster="area_CL1_z")), + ] + ) + assert bc_filter.match_filters(constraint) == expected + + @pytest.mark.parametrize( + "link_id, expected", + [ + ("area_DE_x%area_FR_x", True), + ("AREA_DE_X%area_FR_x", True), + ("area_DE_x%AREA_FR_X", True), + ("AREA_DE_X%AREA_FR_X", True), + ("area_FR_x%area_DE_x", False), + ("fr%de", False), + ("", True), + ], + ) + @pytest.mark.parametrize("cls", [ConstraintOutputBase, ConstraintOutput870]) + def test_filter_by__link_id(self, link_id: str, expected: bool, cls: t.Type[ConstraintOutput]) -> None: + """ + The filter should match if one of the constraint's terms has a cluster name which contains + the filter's cluster name or if the filter is empty. + Comparisons should be case-insensitive. + """ + bc_filter = ConstraintFilters(link_id=link_id) + constraint = cls(id="bc1", name="BC1") + constraint.terms.extend( + [ + ConstraintTerm(weight=2.0, offset=5, data=LinkTerm(area1="area_FR_x", area2="area_DE_x")), + ConstraintTerm(weight=3.0, offset=5, data=LinkTerm(area1="area_IT_y", area2="area_DE_y")), + ConstraintTerm(weight=2.0, offset=5, data=ClusterTerm(area="area_HU_z", cluster="area_CL1_z")), + ] + ) + assert bc_filter.match_filters(constraint) == expected + + @pytest.mark.parametrize( + "cluster_id, expected", + [ + ("area_HU_z.area_CL1_z", True), + ("AREA_HU_Z.area_CL1_z", True), + ("area_HU_z.AREA_CL1_Z", True), + ("AREA_HU_Z.AREA_CL1_Z", True), + ("HU.CL1", False), + ("", True), + ], + ) + @pytest.mark.parametrize("cls", [ConstraintOutputBase, ConstraintOutput870]) + def test_filter_by__cluster_id(self, cluster_id: str, expected: bool, cls: t.Type[ConstraintOutput]) -> None: + """ + The filter should match if one of the constraint's terms has a cluster name which contains + the filter's cluster name or if the filter is empty. + Comparisons should be case-insensitive. + """ + bc_filter = ConstraintFilters(cluster_id=cluster_id) + constraint = cls(id="bc1", name="BC1") + constraint.terms.extend( + [ + ConstraintTerm(weight=2.0, offset=5, data=LinkTerm(area1="area_FR_x", area2="area_DE_x")), + ConstraintTerm(weight=3.0, offset=5, data=LinkTerm(area1="area_IT_y", area2="area_DE_y")), + ConstraintTerm(weight=2.0, offset=5, data=ClusterTerm(area="area_HU_z", cluster="area_CL1_z")), + ] + ) + assert bc_filter.match_filters(constraint) == expected diff --git a/tests/study/storage/variantstudy/business/test_matrix_constants_generator.py b/tests/study/storage/variantstudy/business/test_matrix_constants_generator.py index a216571510..da5ebd91d6 100644 --- a/tests/study/storage/variantstudy/business/test_matrix_constants_generator.py +++ b/tests/study/storage/variantstudy/business/test_matrix_constants_generator.py @@ -46,7 +46,7 @@ def test_get_st_storage(self, tmp_path): matrix_dto5 = generator.matrix_service.get(matrix_id5) assert np.array(matrix_dto5.data).all() == matrix_constants.st_storage.series.inflows.all() - def test_get_binding_constraint(self, tmp_path): + def test_get_binding_constraint_before_v87(self, tmp_path): matrix_content_repository = MatrixContentRepository( bucket_dir=tmp_path, ) @@ -56,19 +56,14 @@ def test_get_binding_constraint(self, tmp_path): ) ) generator.init_constant_matrices() - series = matrix_constants.binding_constraint.series + series = matrix_constants.binding_constraint.series_before_v87 - hourly = generator.get_binding_constraint_hourly() + hourly = generator.get_binding_constraint_hourly_86() hourly_matrix_id = hourly.split(MATRIX_PROTOCOL_PREFIX)[1] hourly_matrix_dto = generator.matrix_service.get(hourly_matrix_id) assert np.array(hourly_matrix_dto.data).all() == series.default_bc_hourly.all() - daily = generator.get_binding_constraint_daily() - daily_matrix_id = daily.split(MATRIX_PROTOCOL_PREFIX)[1] - daily_matrix_dto = generator.matrix_service.get(daily_matrix_id) - assert np.array(daily_matrix_dto.data).all() == series.default_bc_weekly_daily.all() - - weekly = generator.get_binding_constraint_weekly() - weekly_matrix_id = weekly.split(MATRIX_PROTOCOL_PREFIX)[1] - weekly_matrix_dto = generator.matrix_service.get(weekly_matrix_id) - assert np.array(weekly_matrix_dto.data).all() == series.default_bc_weekly_daily.all() + daily_weekly = generator.get_binding_constraint_daily_weekly_86() + matrix_id = daily_weekly.split(MATRIX_PROTOCOL_PREFIX)[1] + matrix_dto = generator.matrix_service.get(matrix_id) + assert np.array(matrix_dto.data).all() == series.default_bc_weekly_daily.all() diff --git a/tests/study/storage/variantstudy/model/test_dbmodel.py b/tests/study/storage/variantstudy/model/test_dbmodel.py index 1e18e4fef1..6ed1bbcba1 100644 --- a/tests/study/storage/variantstudy/model/test_dbmodel.py +++ b/tests/study/storage/variantstudy/model/test_dbmodel.py @@ -156,7 +156,7 @@ def test_init(self, db_session: Session, variant_study_id: str) -> None: "id": command_id, "action": command, "args": json.loads(args), - "version": 1, + "version": 42, } diff --git a/tests/study/storage/variantstudy/test_snapshot_generator.py b/tests/study/storage/variantstudy/test_snapshot_generator.py index 2365049432..e9de3da131 100644 --- a/tests/study/storage/variantstudy/test_snapshot_generator.py +++ b/tests/study/storage/variantstudy/test_snapshot_generator.py @@ -21,11 +21,11 @@ from antarest.study.model import RawStudy, Study, StudyAdditionalData from antarest.study.storage.rawstudy.raw_study_service import RawStudyService from antarest.study.storage.variantstudy.model.dbmodel import CommandBlock, VariantStudy, VariantStudySnapshot -from antarest.study.storage.variantstudy.model.model import CommandDTO, GenerationResultInfoDTO +from antarest.study.storage.variantstudy.model.model import CommandDTO from antarest.study.storage.variantstudy.snapshot_generator import SnapshotGenerator, search_ref_study from antarest.study.storage.variantstudy.variant_study_service import VariantStudyService from tests.db_statement_recorder import DBStatementRecorder -from tests.helpers import with_db_context +from tests.helpers import AnyUUID, with_db_context def _create_variant( @@ -851,15 +851,35 @@ def test_generate__nominal_case( assert len(db_recorder.sql_statements) == 5, str(db_recorder) # Check: the variant generation must succeed. - assert results == GenerationResultInfoDTO( - success=True, - details=[ - ("create_area", True, "Area 'North' created"), - ("create_area", True, "Area 'South' created"), - ("create_link", True, "Link between 'north' and 'south' created"), - ("create_cluster", True, "Thermal cluster 'gas_cluster' added to area 'south'."), + assert results.dict() == { + "success": True, + "details": [ + { + "id": AnyUUID(), + "name": "create_area", + "status": True, + "msg": "Area 'North' created", + }, + { + "id": AnyUUID(), + "name": "create_area", + "status": True, + "msg": "Area 'South' created", + }, + { + "id": AnyUUID(), + "name": "create_link", + "status": True, + "msg": "Link between 'north' and 'south' created", + }, + { + "id": AnyUUID(), + "name": "create_cluster", + "status": True, + "msg": "Thermal cluster 'gas_cluster' added to area 'south'.", + }, ], - ) + } # Check: the variant is correctly generated and all commands are applied. snapshot_dir = variant_study.snapshot_dir @@ -907,13 +927,33 @@ def test_generate__nominal_case( assert list(snapshot_dir.parent.iterdir()) == [snapshot_dir] # Check: the notifications are correctly registered. - assert notifier.notifications == [ # type: ignore + assert notifier.notifications == [ { "details": [ - ["create_area", True, "Area 'North' created"], - ["create_area", True, "Area 'South' created"], - ["create_link", True, "Link between 'north' and 'south' created"], - ["create_cluster", True, "Thermal cluster 'gas_cluster' added to area 'south'."], + { + "id": AnyUUID(as_string=True), + "msg": "Area 'North' created", + "name": "create_area", + "status": True, + }, + { + "id": AnyUUID(as_string=True), + "msg": "Area 'South' created", + "name": "create_area", + "status": True, + }, + { + "id": AnyUUID(as_string=True), + "msg": "Link between 'north' and 'south' created", + "name": "create_link", + "status": True, + }, + { + "id": AnyUUID(as_string=True), + "msg": "Thermal cluster 'gas_cluster' added to area 'south'.", + "name": "create_cluster", + "status": True, + }, ], "success": True, } @@ -996,15 +1036,35 @@ def test_generate__with_denormalize_true( ) # Check the results - assert results == GenerationResultInfoDTO( - success=True, - details=[ - ("create_area", True, "Area 'North' created"), - ("create_area", True, "Area 'South' created"), - ("create_link", True, "Link between 'north' and 'south' created"), - ("create_cluster", True, "Thermal cluster 'gas_cluster' added to area 'south'."), + assert results.dict() == { + "success": True, + "details": [ + { + "id": AnyUUID(), + "name": "create_area", + "status": True, + "msg": "Area 'North' created", + }, + { + "id": AnyUUID(), + "name": "create_area", + "status": True, + "msg": "Area 'South' created", + }, + { + "id": AnyUUID(), + "name": "create_link", + "status": True, + "msg": "Link between 'north' and 'south' created", + }, + { + "id": AnyUUID(), + "name": "create_cluster", + "status": True, + "msg": "Thermal cluster 'gas_cluster' added to area 'south'.", + }, ], - ) + } # Check: the matrices are denormalized (we should have TSV files). snapshot_dir = variant_study.snapshot_dir @@ -1099,15 +1159,35 @@ def test_generate__notification_failure( ) # Check the results - assert results == GenerationResultInfoDTO( - success=True, - details=[ - ("create_area", True, "Area 'North' created"), - ("create_area", True, "Area 'South' created"), - ("create_link", True, "Link between 'north' and 'south' created"), - ("create_cluster", True, "Thermal cluster 'gas_cluster' added to area 'south'."), + assert results.dict() == { + "success": True, + "details": [ + { + "id": AnyUUID(), + "name": "create_area", + "status": True, + "msg": "Area 'North' created", + }, + { + "id": AnyUUID(), + "name": "create_area", + "status": True, + "msg": "Area 'South' created", + }, + { + "id": AnyUUID(), + "name": "create_link", + "status": True, + "msg": "Link between 'north' and 'south' created", + }, + { + "id": AnyUUID(), + "name": "create_cluster", + "status": True, + "msg": "Thermal cluster 'gas_cluster' added to area 'south'.", + }, ], - ) + } # Check th logs assert "Something went wrong" in caplog.text @@ -1161,4 +1241,14 @@ def test_generate__variant_of_variant( ) # Check the results - assert results == GenerationResultInfoDTO(success=True, details=[("create_area", True, "Area 'East' created")]) + assert results.dict() == { + "success": True, + "details": [ + { + "id": AnyUUID(), + "name": "create_area", + "status": True, + "msg": "Area 'East' created", + }, + ], + } diff --git a/tests/study/test_repository.py b/tests/study/test_repository.py index d30c051a6a..f7314cdaaa 100644 --- a/tests/study/test_repository.py +++ b/tests/study/test_repository.py @@ -6,98 +6,142 @@ from sqlalchemy.orm import Session # type: ignore from antarest.core.interfaces.cache import ICache +from antarest.core.model import PublicMode from antarest.login.model import Group, User from antarest.study.model import DEFAULT_WORKSPACE_NAME, RawStudy, Tag -from antarest.study.repository import StudyFilter, StudyMetadataRepository +from antarest.study.repository import ( + AccessPermissions, + StudyFilter, + StudyMetadataRepository, + StudyPagination, + StudySortBy, +) from antarest.study.storage.variantstudy.model.dbmodel import VariantStudy from tests.db_statement_recorder import DBStatementRecorder @pytest.mark.parametrize( - "managed, study_ids, exists, expected_ids", + "managed, study_names, exists, expected_names", [ - (None, [], False, {"5", "6"}), - (None, [], True, {"1", "2", "3", "4", "7", "8"}), - (None, [], None, {"1", "2", "3", "4", "5", "6", "7", "8"}), - (None, [1, 3, 5, 7], False, {"5"}), - (None, [1, 3, 5, 7], True, {"1", "3", "7"}), - (None, [1, 3, 5, 7], None, {"1", "3", "5", "7"}), - (True, [], False, {"5"}), - (True, [], True, {"1", "2", "3", "4", "8"}), - (True, [], None, {"1", "2", "3", "4", "5", "8"}), - (True, [1, 3, 5, 7], False, {"5"}), - (True, [1, 3, 5, 7], True, {"1", "3"}), - (True, [1, 3, 5, 7], None, {"1", "3", "5"}), - (True, [2, 4, 6, 8], True, {"2", "4", "8"}), - (True, [2, 4, 6, 8], None, {"2", "4", "8"}), - (False, [], False, {"6"}), - (False, [], True, {"7"}), - (False, [], None, {"6", "7"}), - (False, [1, 3, 5, 7], False, set()), - (False, [1, 3, 5, 7], True, {"7"}), - (False, [1, 3, 5, 7], None, {"7"}), + (None, [], False, ["s5", "s6"]), + (None, [], True, ["s1", "s2", "s3", "s4", "s7", "s8"]), + (None, [], None, ["s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8"]), + (None, ["s1", "s3", "s5", "s7"], False, ["s5"]), + (None, ["s1", "s3", "s5", "s7"], True, ["s1", "s3", "s7"]), + (None, ["s1", "s3", "s5", "s7"], None, ["s1", "s3", "s5", "s7"]), + (True, [], False, ["s5"]), + (True, [], True, ["s1", "s2", "s3", "s4", "s8"]), + (True, [], None, ["s1", "s2", "s3", "s4", "s5", "s8"]), + (True, ["s1", "s3", "s5", "s7"], False, ["s5"]), + (True, ["s1", "s3", "s5", "s7"], True, ["s1", "s3"]), + (True, ["s1", "s3", "s5", "s7"], None, ["s1", "s3", "s5"]), + (True, ["s2", "s4", "s6", "s8"], True, ["s2", "s4", "s8"]), + (True, ["s2", "s4", "s6", "s8"], None, ["s2", "s4", "s8"]), + (False, [], False, ["s6"]), + (False, [], True, ["s7"]), + (False, [], None, ["s6", "s7"]), + (False, ["s1", "s3", "s5", "s7"], False, []), + (False, ["s1", "s3", "s5", "s7"], True, ["s7"]), + (False, ["s1", "s3", "s5", "s7"], None, ["s7"]), ], ) -def test_repository_get_all__general_case( +def test_get_all__general_case( db_session: Session, managed: t.Union[bool, None], - study_ids: t.Sequence[str], + study_names: t.Sequence[str], exists: t.Union[bool, None], - expected_ids: t.Set[str], + expected_names: t.Sequence[str], ) -> None: test_workspace = "test-repository" icache: Mock = Mock(spec=ICache) repository = StudyMetadataRepository(cache_service=icache, session=db_session) - study_1 = VariantStudy(id=1) - study_2 = VariantStudy(id=2) - study_3 = VariantStudy(id=3) - study_4 = VariantStudy(id=4) - study_5 = RawStudy(id=5, missing=datetime.datetime.now(), workspace=DEFAULT_WORKSPACE_NAME) - study_6 = RawStudy(id=6, missing=datetime.datetime.now(), workspace=test_workspace) - study_7 = RawStudy(id=7, missing=None, workspace=test_workspace) - study_8 = RawStudy(id=8, missing=None, workspace=DEFAULT_WORKSPACE_NAME) - - db_session.add_all([study_1, study_2, study_3, study_4, study_5, study_6, study_7, study_8]) + study_1 = VariantStudy(name="s1") + study_2 = VariantStudy(name="s2") + study_3 = VariantStudy(name="s3") + study_4 = VariantStudy(name="s4") + study_5 = RawStudy(name="s5", missing=datetime.datetime.now(), workspace=DEFAULT_WORKSPACE_NAME) + study_6 = RawStudy(name="s6", missing=datetime.datetime.now(), workspace=test_workspace) + study_7 = RawStudy(name="s7", missing=None, workspace=test_workspace) + study_8 = RawStudy(name="s8", missing=None, workspace=DEFAULT_WORKSPACE_NAME) + + my_studies = [study_1, study_2, study_3, study_4, study_5, study_6, study_7, study_8] + db_session.add_all(my_studies) db_session.commit() + ids_by_names = {s.name: s.id for s in my_studies} + # use the db recorder to check that: # 1- retrieving all studies requires only 1 query # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 + study_filter = StudyFilter( + managed=managed, + study_ids=[ids_by_names[name] for name in study_names], + exists=exists, + access_permissions=AccessPermissions(is_admin=True), + ) with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(managed=managed, study_ids=study_ids, exists=exists)) + all_studies = repository.get_all( + study_filter=study_filter, + sort_by=StudySortBy.NAME_ASC, + ) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies] _ = [s.tags for s in all_studies] assert len(db_recorder.sql_statements) == 1, str(db_recorder) - if expected_ids is not None: - assert {s.id for s in all_studies} == expected_ids + # test that the expected studies are returned + assert [s.name for s in all_studies] == expected_names + + # -- test pagination + page_nb = 1 + page_size = 2 + page_slice = slice(page_nb * page_size, (page_nb + 1) * page_size) + + # test pagination in normal order + with DBStatementRecorder(db_session.bind) as db_recorder: + all_studies = repository.get_all( + study_filter=study_filter, + sort_by=StudySortBy.NAME_ASC, + pagination=StudyPagination(page_nb=page_nb, page_size=page_size), + ) + assert len(db_recorder.sql_statements) == 1, str(db_recorder) + assert [s.name for s in all_studies] == expected_names[page_slice] + # test pagination in reverse order + with DBStatementRecorder(db_session.bind) as db_recorder: + all_studies = repository.get_all( + study_filter=study_filter, + sort_by=StudySortBy.NAME_DESC, + pagination=StudyPagination(page_nb=page_nb, page_size=page_size), + ) + assert len(db_recorder.sql_statements) == 1, str(db_recorder) + assert [s.name for s in all_studies] == expected_names[::-1][page_slice] -def test_repository_get_all__incompatible_case( + +def test_get_all__incompatible_case( db_session: Session, ) -> None: test_workspace = "workspace1" icache: Mock = Mock(spec=ICache) repository = StudyMetadataRepository(cache_service=icache, session=db_session) - study_1 = VariantStudy(id=1) - study_2 = VariantStudy(id=2) - study_3 = VariantStudy(id=3) - study_4 = VariantStudy(id=4) - study_5 = RawStudy(id=5, missing=datetime.datetime.now(), workspace=DEFAULT_WORKSPACE_NAME) - study_6 = RawStudy(id=6, missing=datetime.datetime.now(), workspace=test_workspace) - study_7 = RawStudy(id=7, missing=None, workspace=test_workspace) - study_8 = RawStudy(id=8, missing=None, workspace=DEFAULT_WORKSPACE_NAME) + study_1 = VariantStudy(id=1, name="study-1") + study_2 = VariantStudy(id=2, name="study-2") + study_3 = VariantStudy(id=3, name="study-3") + study_4 = VariantStudy(id=4, name="study-4") + study_5 = RawStudy(id=5, name="study-5", missing=datetime.datetime.now(), workspace=DEFAULT_WORKSPACE_NAME) + study_6 = RawStudy(id=6, name="study-6", missing=datetime.datetime.now(), workspace=test_workspace) + study_7 = RawStudy(id=7, name="study-7", missing=None, workspace=test_workspace) + study_8 = RawStudy(id=8, name="study-8", missing=None, workspace=DEFAULT_WORKSPACE_NAME) db_session.add_all([study_1, study_2, study_3, study_4, study_5, study_6, study_7, study_8]) db_session.commit() # case 1 - study_filter = StudyFilter(managed=False, variant=True) + study_filter = StudyFilter(managed=False, variant=True, access_permissions=AccessPermissions(is_admin=True)) with DBStatementRecorder(db_session.bind) as db_recorder: all_studies = repository.get_all(study_filter=study_filter) _ = [s.owner for s in all_studies] @@ -108,7 +152,9 @@ def test_repository_get_all__incompatible_case( assert not {s.id for s in all_studies} # case 2 - study_filter = StudyFilter(workspace=test_workspace, variant=True) + study_filter = StudyFilter( + workspace=test_workspace, variant=True, access_permissions=AccessPermissions(is_admin=True) + ) with DBStatementRecorder(db_session.bind) as db_recorder: all_studies = repository.get_all(study_filter=study_filter) _ = [s.owner for s in all_studies] @@ -119,7 +165,7 @@ def test_repository_get_all__incompatible_case( assert not {s.id for s in all_studies} # case 3 - study_filter = StudyFilter(exists=False, variant=True) + study_filter = StudyFilter(exists=False, variant=True, access_permissions=AccessPermissions(is_admin=True)) with DBStatementRecorder(db_session.bind) as db_recorder: all_studies = repository.get_all(study_filter=study_filter) _ = [s.owner for s in all_studies] @@ -133,21 +179,21 @@ def test_repository_get_all__incompatible_case( @pytest.mark.parametrize( "name, expected_ids", [ - ("", {"1", "2", "3", "4", "5", "6", "7", "8"}), - ("specie", {"1", "2", "3", "4", "5", "6", "7", "8"}), - ("prefix-specie", {"2", "3", "6", "7"}), - ("variant", {"1", "2", "3", "4"}), - ("variant-suffix", {"3", "4"}), - ("raw", {"5", "6", "7", "8"}), - ("raw-suffix", {"7", "8"}), - ("prefix-variant", set()), - ("specie-suffix", set()), + ("", ["1", "2", "3", "4", "5", "6", "7", "8"]), + ("specie", ["1", "2", "3", "4", "5", "6", "7", "8"]), + ("prefix-specie", ["2", "3", "6", "7"]), + ("variant", ["1", "2", "3", "4"]), + ("variant-suffix", ["3", "4"]), + ("raw", ["5", "6", "7", "8"]), + ("raw-suffix", ["7", "8"]), + ("prefix-variant", []), + ("specie-suffix", []), ], ) -def test_repository_get_all__study_name_filter( +def test_get_all__study_name_filter( db_session: Session, name: str, - expected_ids: t.Set[str], + expected_ids: t.List[str], ) -> None: icache: Mock = Mock(spec=ICache) repository = StudyMetadataRepository(cache_service=icache, session=db_session) @@ -161,6 +207,10 @@ def test_repository_get_all__study_name_filter( study_7 = RawStudy(id=7, name="prefix-specie-raw-suffix") study_8 = RawStudy(id=8, name="specie-raw-suffix") + mapping_ids_names = { + str(s.id): s.name for s in [study_1, study_2, study_3, study_4, study_5, study_6, study_7, study_8] + } + db_session.add_all([study_1, study_2, study_3, study_4, study_5, study_6, study_7, study_8]) db_session.commit() @@ -169,7 +219,9 @@ def test_repository_get_all__study_name_filter( # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(name=name)) + all_studies = repository.get_all( + study_filter=StudyFilter(name=name, access_permissions=AccessPermissions(is_admin=True)) + ) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies] @@ -177,34 +229,45 @@ def test_repository_get_all__study_name_filter( assert len(db_recorder.sql_statements) == 1, str(db_recorder) if expected_ids is not None: - assert {s.id for s in all_studies} == expected_ids + assert sorted(s.id for s in all_studies) == expected_ids + + # test pagination + with DBStatementRecorder(db_session.bind) as db_recorder: + all_studies = repository.get_all( + study_filter=StudyFilter(name=name, access_permissions=AccessPermissions(is_admin=True)), + pagination=StudyPagination(page_nb=1, page_size=2), + ) + assert len(all_studies) == max(0, min(len(expected_ids) - 2, 2)) + name_sorted_expected_studies = sorted(expected_ids, key=lambda s_id: mapping_ids_names[s_id]) + assert sorted(s.id for s in all_studies) == name_sorted_expected_studies[2:4] + assert len(db_recorder.sql_statements) == 1, str(db_recorder) @pytest.mark.parametrize( "managed, expected_ids", [ - (None, {"1", "2", "3", "4", "5", "6", "7", "8"}), - (True, {"1", "2", "3", "4", "5", "8"}), - (False, {"6", "7"}), + (None, ["1", "2", "3", "4", "5", "6", "7", "8"]), + (True, ["1", "2", "3", "4", "5", "8"]), + (False, ["6", "7"]), ], ) -def test_repository_get_all__managed_study_filter( +def test_get_all__managed_study_filter( db_session: Session, managed: t.Optional[bool], - expected_ids: t.Set[str], + expected_ids: t.List[str], ) -> None: test_workspace = "test-workspace" icache: Mock = Mock(spec=ICache) repository = StudyMetadataRepository(cache_service=icache, session=db_session) - study_1 = VariantStudy(id=1) - study_2 = VariantStudy(id=2) - study_3 = VariantStudy(id=3) - study_4 = VariantStudy(id=4) - study_5 = RawStudy(id=5, workspace=DEFAULT_WORKSPACE_NAME) - study_6 = RawStudy(id=6, workspace=test_workspace) - study_7 = RawStudy(id=7, workspace=test_workspace) - study_8 = RawStudy(id=8, workspace=DEFAULT_WORKSPACE_NAME) + study_1 = VariantStudy(id=1, name="study-1") + study_2 = VariantStudy(id=2, name="study-2") + study_3 = VariantStudy(id=3, name="study-3") + study_4 = VariantStudy(id=4, name="study-4") + study_5 = RawStudy(id=5, name="study-5", workspace=DEFAULT_WORKSPACE_NAME) + study_6 = RawStudy(id=6, name="study-6", workspace=test_workspace) + study_7 = RawStudy(id=7, name="study-7", workspace=test_workspace) + study_8 = RawStudy(id=8, name="study-8", workspace=DEFAULT_WORKSPACE_NAME) db_session.add_all([study_1, study_2, study_3, study_4, study_5, study_6, study_7, study_8]) db_session.commit() @@ -214,7 +277,9 @@ def test_repository_get_all__managed_study_filter( # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(managed=managed)) + all_studies = repository.get_all( + study_filter=StudyFilter(managed=managed, access_permissions=AccessPermissions(is_admin=True)) + ) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies] @@ -222,29 +287,39 @@ def test_repository_get_all__managed_study_filter( assert len(db_recorder.sql_statements) == 1, str(db_recorder) if expected_ids is not None: - assert {s.id for s in all_studies} == expected_ids + assert sorted(s.id for s in all_studies) == expected_ids + + # test pagination + with DBStatementRecorder(db_session.bind) as db_recorder: + all_studies = repository.get_all( + study_filter=StudyFilter(managed=managed, access_permissions=AccessPermissions(is_admin=True)), + pagination=StudyPagination(page_nb=1, page_size=2), + ) + assert len(all_studies) == max(0, min(len(expected_ids) - 2, 2)) + assert sorted(s.id for s in all_studies) == expected_ids[2:4] + assert len(db_recorder.sql_statements) == 1, str(db_recorder) @pytest.mark.parametrize( "archived, expected_ids", [ - (None, {"1", "2", "3", "4"}), - (True, {"1", "3"}), - (False, {"2", "4"}), + (None, ["1", "2", "3", "4"]), + (True, ["1", "3"]), + (False, ["2", "4"]), ], ) -def test_repository_get_all__archived_study_filter( +def test_get_all__archived_study_filter( db_session: Session, archived: t.Optional[bool], - expected_ids: t.Set[str], + expected_ids: t.List[str], ) -> None: icache: Mock = Mock(spec=ICache) repository = StudyMetadataRepository(cache_service=icache, session=db_session) - study_1 = VariantStudy(id=1, archived=True) - study_2 = VariantStudy(id=2, archived=False) - study_3 = RawStudy(id=3, archived=True) - study_4 = RawStudy(id=4, archived=False) + study_1 = VariantStudy(id=1, name="study-1", archived=True) + study_2 = VariantStudy(id=2, name="study-2", archived=False) + study_3 = RawStudy(id=3, name="study-3", archived=True) + study_4 = RawStudy(id=4, name="study-4", archived=False) db_session.add_all([study_1, study_2, study_3, study_4]) db_session.commit() @@ -253,8 +328,9 @@ def test_repository_get_all__archived_study_filter( # 1- retrieving all studies requires only 1 query # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 + study_filter = StudyFilter(archived=archived, access_permissions=AccessPermissions(is_admin=True)) with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(archived=archived)) + all_studies = repository.get_all(study_filter=study_filter) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies] @@ -262,29 +338,38 @@ def test_repository_get_all__archived_study_filter( assert len(db_recorder.sql_statements) == 1, str(db_recorder) if expected_ids is not None: - assert {s.id for s in all_studies} == expected_ids + assert sorted(s.id for s in all_studies) == expected_ids + + # test pagination + with DBStatementRecorder(db_session.bind) as db_recorder: + all_studies = repository.get_all( + study_filter=study_filter, + pagination=StudyPagination(page_nb=1, page_size=1), + ) + assert len(all_studies) == max(0, min(len(expected_ids) - 1, 1)) + assert len(db_recorder.sql_statements) == 1, str(db_recorder) @pytest.mark.parametrize( "variant, expected_ids", [ - (None, {"1", "2", "3", "4"}), - (True, {"1", "2"}), - (False, {"3", "4"}), + (None, ["1", "2", "3", "4"]), + (True, ["1", "2"]), + (False, ["3", "4"]), ], ) -def test_repository_get_all__variant_study_filter( +def test_get_all__variant_study_filter( db_session: Session, variant: t.Optional[bool], - expected_ids: t.Set[str], + expected_ids: t.List[str], ) -> None: icache: Mock = Mock(spec=ICache) repository = StudyMetadataRepository(cache_service=icache, session=db_session) - study_1 = VariantStudy(id=1) - study_2 = VariantStudy(id=2) - study_3 = RawStudy(id=3) - study_4 = RawStudy(id=4) + study_1 = VariantStudy(id=1, name="study-1") + study_2 = VariantStudy(id=2, name="study-2") + study_3 = RawStudy(id=3, name="study-3") + study_4 = RawStudy(id=4, name="study-4") db_session.add_all([study_1, study_2, study_3, study_4]) db_session.commit() @@ -293,8 +378,9 @@ def test_repository_get_all__variant_study_filter( # 1- retrieving all studies requires only 1 query # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 + study_filter = StudyFilter(variant=variant, access_permissions=AccessPermissions(is_admin=True)) with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(variant=variant)) + all_studies = repository.get_all(study_filter=study_filter) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies] @@ -302,31 +388,40 @@ def test_repository_get_all__variant_study_filter( assert len(db_recorder.sql_statements) == 1, str(db_recorder) if expected_ids is not None: - assert {s.id for s in all_studies} == expected_ids + assert sorted(s.id for s in all_studies) == expected_ids + + # test pagination + with DBStatementRecorder(db_session.bind) as db_recorder: + all_studies = repository.get_all( + study_filter=study_filter, + pagination=StudyPagination(page_nb=1, page_size=1), + ) + assert len(all_studies) == max(0, min(len(expected_ids) - 1, 1)) + assert len(db_recorder.sql_statements) == 1, str(db_recorder) @pytest.mark.parametrize( "versions, expected_ids", [ - ([], {"1", "2", "3", "4"}), - (["1", "2"], {"1", "2", "3", "4"}), - (["1"], {"1", "3"}), - (["2"], {"2", "4"}), - (["3"], set()), + ([], ["1", "2", "3", "4"]), + (["1", "2"], ["1", "2", "3", "4"]), + (["1"], ["1", "3"]), + (["2"], ["2", "4"]), + (["3"], []), ], ) -def test_repository_get_all__study_version_filter( +def test_get_all__study_version_filter( db_session: Session, versions: t.Sequence[str], - expected_ids: t.Set[str], + expected_ids: t.List[str], ) -> None: icache: Mock = Mock(spec=ICache) repository = StudyMetadataRepository(cache_service=icache, session=db_session) - study_1 = VariantStudy(id=1, version="1") - study_2 = VariantStudy(id=2, version="2") - study_3 = RawStudy(id=3, version="1") - study_4 = RawStudy(id=4, version="2") + study_1 = VariantStudy(id=1, name="study-1", version="1") + study_2 = VariantStudy(id=2, name="study-2", version="2") + study_3 = RawStudy(id=3, name="study-3", version="1") + study_4 = RawStudy(id=4, name="study-4", version="2") db_session.add_all([study_1, study_2, study_3, study_4]) db_session.commit() @@ -335,8 +430,9 @@ def test_repository_get_all__study_version_filter( # 1- retrieving all studies requires only 1 query # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 + study_filter = StudyFilter(versions=versions, access_permissions=AccessPermissions(is_admin=True)) with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(versions=versions)) + all_studies = repository.get_all(study_filter=study_filter) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies] @@ -344,23 +440,32 @@ def test_repository_get_all__study_version_filter( assert len(db_recorder.sql_statements) == 1, str(db_recorder) if expected_ids is not None: - assert {s.id for s in all_studies} == expected_ids + assert sorted(s.id for s in all_studies) == expected_ids + + # test pagination + with DBStatementRecorder(db_session.bind) as db_recorder: + all_studies = repository.get_all( + study_filter=study_filter, + pagination=StudyPagination(page_nb=1, page_size=1), + ) + assert len(all_studies) == max(0, min(len(expected_ids) - 1, 1)) + assert len(db_recorder.sql_statements) == 1, str(db_recorder) @pytest.mark.parametrize( "users, expected_ids", [ - ([], {"1", "2", "3", "4"}), - (["1000", "2000"], {"1", "2", "3", "4"}), - (["1000"], {"1", "3"}), - (["2000"], {"2", "4"}), - (["3000"], set()), + ([], ["1", "2", "3", "4"]), + (["1000", "2000"], ["1", "2", "3", "4"]), + (["1000"], ["1", "3"]), + (["2000"], ["2", "4"]), + (["3000"], []), ], ) -def test_repository_get_all__study_users_filter( +def test_get_all__study_users_filter( db_session: Session, users: t.Sequence["int"], - expected_ids: t.Set[str], + expected_ids: t.List[str], ) -> None: icache: Mock = Mock(spec=ICache) repository = StudyMetadataRepository(cache_service=icache, session=db_session) @@ -368,10 +473,10 @@ def test_repository_get_all__study_users_filter( test_user_1 = User(id=1000) test_user_2 = User(id=2000) - study_1 = VariantStudy(id=1, owner=test_user_1) - study_2 = VariantStudy(id=2, owner=test_user_2) - study_3 = RawStudy(id=3, owner=test_user_1) - study_4 = RawStudy(id=4, owner=test_user_2) + study_1 = VariantStudy(id=1, name="study-1", owner=test_user_1) + study_2 = VariantStudy(id=2, name="study-2", owner=test_user_2) + study_3 = RawStudy(id=3, name="study-3", owner=test_user_1) + study_4 = RawStudy(id=4, name="study-4", owner=test_user_2) db_session.add_all([test_user_1, test_user_2]) db_session.commit() @@ -384,7 +489,9 @@ def test_repository_get_all__study_users_filter( # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(users=users)) + all_studies = repository.get_all( + study_filter=StudyFilter(users=users, access_permissions=AccessPermissions(is_admin=True)) + ) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies] @@ -392,23 +499,33 @@ def test_repository_get_all__study_users_filter( assert len(db_recorder.sql_statements) == 1, str(db_recorder) if expected_ids is not None: - assert {s.id for s in all_studies} == expected_ids + assert sorted(s.id for s in all_studies) == expected_ids + + # test pagination + with DBStatementRecorder(db_session.bind) as db_recorder: + all_studies = repository.get_all( + study_filter=StudyFilter(users=users, access_permissions=AccessPermissions(is_admin=True)), + pagination=StudyPagination(page_nb=1, page_size=2), + ) + assert len(all_studies) == max(0, min(len(expected_ids) - 2, 2)) + assert sorted(s.id for s in all_studies) == expected_ids[2:4] + assert len(db_recorder.sql_statements) == 1, str(db_recorder) @pytest.mark.parametrize( "groups, expected_ids", [ - ([], {"1", "2", "3", "4"}), - (["1000", "2000"], {"1", "2", "3", "4"}), - (["1000"], {"1", "2", "4"}), - (["2000"], {"2", "3"}), - (["3000"], set()), + ([], ["1", "2", "3", "4"]), + (["1000", "2000"], ["1", "2", "3", "4"]), + (["1000"], ["1", "2", "4"]), + (["2000"], ["2", "3"]), + (["3000"], []), ], ) -def test_repository_get_all__study_groups_filter( +def test_get_all__study_groups_filter( db_session: Session, groups: t.Sequence[str], - expected_ids: t.Set[str], + expected_ids: t.List[str], ) -> None: icache: Mock = Mock(spec=ICache) repository = StudyMetadataRepository(cache_service=icache, session=db_session) @@ -416,10 +533,10 @@ def test_repository_get_all__study_groups_filter( test_group_1 = Group(id=1000) test_group_2 = Group(id=2000) - study_1 = VariantStudy(id=1, groups=[test_group_1]) - study_2 = VariantStudy(id=2, groups=[test_group_1, test_group_2]) - study_3 = RawStudy(id=3, groups=[test_group_2]) - study_4 = RawStudy(id=4, groups=[test_group_1]) + study_1 = VariantStudy(id=1, name="study-1", groups=[test_group_1]) + study_2 = VariantStudy(id=2, name="study-2", groups=[test_group_1, test_group_2]) + study_3 = RawStudy(id=3, name="study-3", groups=[test_group_2]) + study_4 = RawStudy(id=4, name="study-4", groups=[test_group_1]) db_session.add_all([test_group_1, test_group_2]) db_session.commit() @@ -432,7 +549,9 @@ def test_repository_get_all__study_groups_filter( # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(groups=groups)) + all_studies = repository.get_all( + study_filter=StudyFilter(groups=groups, access_permissions=AccessPermissions(is_admin=True)) + ) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies] @@ -440,32 +559,42 @@ def test_repository_get_all__study_groups_filter( assert len(db_recorder.sql_statements) == 1, str(db_recorder) if expected_ids is not None: - assert {s.id for s in all_studies} == expected_ids + assert sorted(s.id for s in all_studies) == expected_ids + + # test pagination + with DBStatementRecorder(db_session.bind) as db_recorder: + all_studies = repository.get_all( + study_filter=StudyFilter(groups=groups, access_permissions=AccessPermissions(is_admin=True)), + pagination=StudyPagination(page_nb=1, page_size=2), + ) + assert len(all_studies) == max(0, min(len(expected_ids) - 2, 2)) + assert sorted(s.id for s in all_studies) == expected_ids[2:4] + assert len(db_recorder.sql_statements) == 1, str(db_recorder) @pytest.mark.parametrize( "study_ids, expected_ids", [ - ([], {"1", "2", "3", "4"}), - (["1", "2", "3", "4"], {"1", "2", "3", "4"}), - (["1", "2", "4"], {"1", "2", "4"}), - (["2", "3"], {"2", "3"}), - (["2"], {"2"}), - (["3000"], set()), + ([], ["1", "2", "3", "4"]), + (["1", "2", "3", "4"], ["1", "2", "3", "4"]), + (["1", "2", "4"], ["1", "2", "4"]), + (["2", "3"], ["2", "3"]), + (["2"], ["2"]), + (["3000"], []), ], ) -def test_repository_get_all__study_ids_filter( +def test_get_all__study_ids_filter( db_session: Session, study_ids: t.Sequence[str], - expected_ids: t.Set[str], + expected_ids: t.List[str], ) -> None: icache: Mock = Mock(spec=ICache) repository = StudyMetadataRepository(cache_service=icache, session=db_session) - study_1 = VariantStudy(id=1) - study_2 = VariantStudy(id=2) - study_3 = RawStudy(id=3) - study_4 = RawStudy(id=4) + study_1 = VariantStudy(id=1, name="study-1") + study_2 = VariantStudy(id=2, name="study-2") + study_3 = RawStudy(id=3, name="study-3") + study_4 = RawStudy(id=4, name="study-4") db_session.add_all([study_1, study_2, study_3, study_4]) db_session.commit() @@ -475,7 +604,9 @@ def test_repository_get_all__study_ids_filter( # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(study_ids=study_ids)) + all_studies = repository.get_all( + study_filter=StudyFilter(study_ids=study_ids, access_permissions=AccessPermissions(is_admin=True)) + ) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies] @@ -483,29 +614,39 @@ def test_repository_get_all__study_ids_filter( assert len(db_recorder.sql_statements) == 1, str(db_recorder) if expected_ids is not None: - assert {s.id for s in all_studies} == expected_ids + assert sorted(s.id for s in all_studies) == expected_ids + + # test pagination + with DBStatementRecorder(db_session.bind) as db_recorder: + all_studies = repository.get_all( + study_filter=StudyFilter(study_ids=study_ids, access_permissions=AccessPermissions(is_admin=True)), + pagination=StudyPagination(page_nb=1, page_size=2), + ) + assert len(all_studies) == max(0, min(len(expected_ids) - 2, 2)) + assert sorted(s.id for s in all_studies) == expected_ids[2:4] + assert len(db_recorder.sql_statements) == 1, str(db_recorder) @pytest.mark.parametrize( "exists, expected_ids", [ - (None, {"1", "2", "3", "4"}), - (True, {"1", "2", "4"}), - (False, {"3"}), + (None, ["1", "2", "3", "4"]), + (True, ["1", "2", "4"]), + (False, ["3"]), ], ) -def test_repository_get_all__study_existence_filter( +def test_get_all__study_existence_filter( db_session: Session, exists: t.Optional[bool], - expected_ids: t.Set[str], + expected_ids: t.List[str], ) -> None: icache: Mock = Mock(spec=ICache) repository = StudyMetadataRepository(cache_service=icache, session=db_session) - study_1 = VariantStudy(id=1) - study_2 = VariantStudy(id=2) - study_3 = RawStudy(id=3, missing=datetime.datetime.now()) - study_4 = RawStudy(id=4) + study_1 = VariantStudy(id=1, name="study-1") + study_2 = VariantStudy(id=2, name="study-2") + study_3 = RawStudy(id=3, name="study-3", missing=datetime.datetime.now()) + study_4 = RawStudy(id=4, name="study-4") db_session.add_all([study_1, study_2, study_3, study_4]) db_session.commit() @@ -515,7 +656,9 @@ def test_repository_get_all__study_existence_filter( # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(exists=exists)) + all_studies = repository.get_all( + study_filter=StudyFilter(exists=exists, access_permissions=AccessPermissions(is_admin=True)) + ) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies] @@ -523,30 +666,40 @@ def test_repository_get_all__study_existence_filter( assert len(db_recorder.sql_statements) == 1, str(db_recorder) if expected_ids is not None: - assert {s.id for s in all_studies} == expected_ids + assert sorted(s.id for s in all_studies) == expected_ids + + # test pagination + with DBStatementRecorder(db_session.bind) as db_recorder: + all_studies = repository.get_all( + study_filter=StudyFilter(exists=exists, access_permissions=AccessPermissions(is_admin=True)), + pagination=StudyPagination(page_nb=1, page_size=2), + ) + assert len(all_studies) == max(0, min(len(expected_ids) - 2, 2)) + assert sorted(s.id for s in all_studies) == expected_ids[2:4] + assert len(db_recorder.sql_statements) == 1, str(db_recorder) @pytest.mark.parametrize( "workspace, expected_ids", [ - ("", {"1", "2", "3", "4"}), - ("workspace-1", {"3"}), - ("workspace-2", {"4"}), - ("workspace-3", set()), + ("", ["1", "2", "3", "4"]), + ("workspace-1", ["3"]), + ("workspace-2", ["4"]), + ("workspace-3", []), ], ) -def test_repository_get_all__study_workspace_filter( +def test_get_all__study_workspace_filter( db_session: Session, workspace: str, - expected_ids: t.Set[str], + expected_ids: t.List[str], ) -> None: icache: Mock = Mock(spec=ICache) repository = StudyMetadataRepository(cache_service=icache, session=db_session) - study_1 = VariantStudy(id=1) - study_2 = VariantStudy(id=2) - study_3 = RawStudy(id=3, workspace="workspace-1") - study_4 = RawStudy(id=4, workspace="workspace-2") + study_1 = VariantStudy(id=1, name="study-1") + study_2 = VariantStudy(id=2, name="study-2") + study_3 = RawStudy(id=3, name="study-3", workspace="workspace-1") + study_4 = RawStudy(id=4, name="study-4", workspace="workspace-2") db_session.add_all([study_1, study_2, study_3, study_4]) db_session.commit() @@ -556,7 +709,9 @@ def test_repository_get_all__study_workspace_filter( # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(workspace=workspace)) + all_studies = repository.get_all( + study_filter=StudyFilter(workspace=workspace, access_permissions=AccessPermissions(is_admin=True)) + ) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies] @@ -564,32 +719,42 @@ def test_repository_get_all__study_workspace_filter( assert len(db_recorder.sql_statements) == 1, str(db_recorder) if expected_ids is not None: - assert {s.id for s in all_studies} == expected_ids + assert sorted(s.id for s in all_studies) == expected_ids + + # test pagination + with DBStatementRecorder(db_session.bind) as db_recorder: + all_studies = repository.get_all( + study_filter=StudyFilter(workspace=workspace, access_permissions=AccessPermissions(is_admin=True)), + pagination=StudyPagination(page_nb=1, page_size=2), + ) + assert len(all_studies) == max(0, min(len(expected_ids) - 2, 2)) + assert sorted(s.id for s in all_studies) == expected_ids[2:4] + assert len(db_recorder.sql_statements) == 1, str(db_recorder) @pytest.mark.parametrize( "folder, expected_ids", [ - ("", {"1", "2", "3", "4"}), - ("/home/folder-", {"1", "2", "3", "4"}), - ("/home/folder-1", {"1", "3"}), - ("/home/folder-2", {"2", "4"}), - ("/home/folder-3", set()), - ("folder-1", set()), + ("", ["1", "2", "3", "4"]), + ("/home/folder-", ["1", "2", "3", "4"]), + ("/home/folder-1", ["1", "3"]), + ("/home/folder-2", ["2", "4"]), + ("/home/folder-3", []), + ("folder-1", []), ], ) -def test_repository_get_all__study_folder_filter( +def test_get_all__study_folder_filter( db_session: Session, folder: str, - expected_ids: t.Set[str], + expected_ids: t.List[str], ) -> None: icache: Mock = Mock(spec=ICache) repository = StudyMetadataRepository(cache_service=icache, session=db_session) - study_1 = VariantStudy(id=1, folder="/home/folder-1") - study_2 = VariantStudy(id=2, folder="/home/folder-2") - study_3 = RawStudy(id=3, folder="/home/folder-1") - study_4 = RawStudy(id=4, folder="/home/folder-2") + study_1 = VariantStudy(id=1, name="study-1", folder="/home/folder-1") + study_2 = VariantStudy(id=2, name="study-2", folder="/home/folder-2") + study_3 = RawStudy(id=3, name="study-3", folder="/home/folder-1") + study_4 = RawStudy(id=4, name="study-4", folder="/home/folder-2") db_session.add_all([study_1, study_2, study_3, study_4]) db_session.commit() @@ -598,8 +763,9 @@ def test_repository_get_all__study_folder_filter( # 1- retrieving all studies requires only 1 query # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 + study_filter = StudyFilter(folder=folder, access_permissions=AccessPermissions(is_admin=True)) with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(folder=folder)) + all_studies = repository.get_all(study_filter=study_filter) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies] @@ -608,39 +774,48 @@ def test_repository_get_all__study_folder_filter( assert len(db_recorder.sql_statements) == 1, str(db_recorder) if expected_ids is not None: - assert {s.id for s in all_studies} == expected_ids + assert sorted(s.id for s in all_studies) == expected_ids + + # test pagination + with DBStatementRecorder(db_session.bind) as db_recorder: + all_studies = repository.get_all( + study_filter=study_filter, + pagination=StudyPagination(page_nb=1, page_size=1), + ) + assert len(all_studies) == max(0, min(len(expected_ids) - 1, 1)) + assert len(db_recorder.sql_statements) == 1, str(db_recorder) @pytest.mark.parametrize( "tags, expected_ids", [ - ([], {"1", "2", "3", "4", "5", "6", "7", "8"}), - (["decennial"], {"2", "4", "6", "8"}), - (["winter_transition"], {"3", "4", "7", "8"}), - (["decennial", "winter_transition"], {"2", "3", "4", "6", "7", "8"}), - (["no-study-tag"], set()), + ([], ["1", "2", "3", "4", "5", "6", "7", "8"]), + (["decennial"], ["2", "4", "6", "8"]), + (["winter_transition"], ["3", "4", "7", "8"]), + (["decennial", "winter_transition"], ["2", "3", "4", "6", "7", "8"]), + (["no-study-tag"], []), ], ) -def test_repository_get_all__study_tags_filter( +def test_get_all__study_tags_filter( db_session: Session, tags: t.Sequence[str], - expected_ids: t.Set[str], + expected_ids: t.List[str], ) -> None: icache: Mock = Mock(spec=ICache) repository = StudyMetadataRepository(cache_service=icache, session=db_session) test_tag_1 = Tag(label="hidden-tag") test_tag_2 = Tag(label="decennial") - test_tag_3 = Tag(label="winter_transition") + test_tag_3 = Tag(label="Winter_Transition") # note the different case - study_1 = VariantStudy(id=1, tags=[test_tag_1]) - study_2 = VariantStudy(id=2, tags=[test_tag_2]) - study_3 = VariantStudy(id=3, tags=[test_tag_3]) - study_4 = VariantStudy(id=4, tags=[test_tag_2, test_tag_3]) - study_5 = RawStudy(id=5, tags=[test_tag_1]) - study_6 = RawStudy(id=6, tags=[test_tag_2]) - study_7 = RawStudy(id=7, tags=[test_tag_3]) - study_8 = RawStudy(id=8, tags=[test_tag_2, test_tag_3]) + study_1 = VariantStudy(id=1, name="study-1", tags=[test_tag_1]) + study_2 = VariantStudy(id=2, name="study-2", tags=[test_tag_2]) + study_3 = VariantStudy(id=3, name="study-3", tags=[test_tag_3]) + study_4 = VariantStudy(id=4, name="study-4", tags=[test_tag_2, test_tag_3]) + study_5 = RawStudy(id=5, name="study-5", tags=[test_tag_1]) + study_6 = RawStudy(id=6, name="study-6", tags=[test_tag_2]) + study_7 = RawStudy(id=7, name="study-7", tags=[test_tag_3]) + study_8 = RawStudy(id=8, name="study-8", tags=[test_tag_2, test_tag_3]) db_session.add_all([study_1, study_2, study_3, study_4, study_5, study_6, study_7, study_8]) db_session.commit() @@ -650,7 +825,172 @@ def test_repository_get_all__study_tags_filter( # 2- accessing studies attributes does not require additional queries to db # 3- having an exact total of queries equals to 1 with DBStatementRecorder(db_session.bind) as db_recorder: - all_studies = repository.get_all(study_filter=StudyFilter(tags=tags)) + all_studies = repository.get_all( + study_filter=StudyFilter(tags=tags, access_permissions=AccessPermissions(is_admin=True)) + ) + _ = [s.owner for s in all_studies] + _ = [s.groups for s in all_studies] + _ = [s.additional_data for s in all_studies] + _ = [s.tags for s in all_studies] + + assert len(db_recorder.sql_statements) == 1, str(db_recorder) + + if expected_ids is not None: + assert sorted(s.id for s in all_studies) == expected_ids + + # test pagination + with DBStatementRecorder(db_session.bind) as db_recorder: + all_studies = repository.get_all( + study_filter=StudyFilter(tags=tags, access_permissions=AccessPermissions(is_admin=True)), + pagination=StudyPagination(page_nb=1, page_size=2), + ) + assert len(all_studies) == max(0, min(len(expected_ids) - 2, 2)) + assert sorted(s.id for s in all_studies) == expected_ids[2:4] + assert len(db_recorder.sql_statements) == 1, str(db_recorder) + + +@pytest.mark.parametrize( + "user_id, study_groups, expected_ids", + [ + # fmt: off + (101, [], ["1", "2", "5", "6", "7", "8", "9", "10", "13", "14", "15", "16", "17", "18", + "21", "22", "23", "24", "25", "26", "29", "30", "31", "32", "34"]), + (101, ["101"], ["1", "7", "8", "9", "17", "23", "24", "25"]), + (101, ["102"], ["2", "5", "6", "7", "8", "9", "18", "21", "22", "23", "24", "25", "34"]), + (101, ["103"], []), + (101, ["101", "102"], ["1", "2", "5", "6", "7", "8", "9", "17", "18", "21", "22", "23", "24", "25", "34"]), + (101, ["101", "103"], ["1", "7", "8", "9", "17", "23", "24", "25"]), + (101, ["102", "103"], ["2", "5", "6", "7", "8", "9", "18", "21", "22", "23", "24", "25", "34"]), + (101, ["101", "102", "103"], ["1", "2", "5", "6", "7", "8", "9", "17", "18", "21", "22", + "23", "24", "25", "34"]), + (102, [], ["1", "3", "4", "5", "7", "8", "9", "11", "13", "14", "15", "16", "17", "19", + "20", "21", "23", "24", "25", "27", "29", "30", "31", "32", "33"]), + (102, ["101"], ["1", "3", "4", "7", "8", "9", "17", "19", "20", "23", "24", "25", "33"]), + (102, ["102"], ["5", "7", "8", "9", "21", "23", "24", "25"]), + (102, ["103"], []), + (102, ["101", "102"], ["1", "3", "4", "5", "7", "8", "9", "17", "19", "20", "21", "23", "24", "25", "33"]), + (102, ["101", "103"], ["1", "3", "4", "7", "8", "9", "17", "19", "20", "23", "24", "25", "33"]), + (102, ["102", "103"], ["5", "7", "8", "9", "21", "23", "24", "25"]), + (102, ["101", "102", "103"], ["1", "3", "4", "5", "7", "8", "9", "17", "19", "20", "21", + "23", "24", "25", "33"]), + (103, [], ["13", "14", "15", "16", "29", "30", "31", "32", "33", "34", "35", "36"]), + (103, ["101"], ["33"]), + (103, ["102"], ["34"]), + (103, ["103"], []), + (103, ["101", "102"], ["33", "34"]), + (103, ["101", "103"], ["33"]), + (103, ["102", "103"], ["34"]), + (103, ["101", "102", "103"], ["33", "34"]), + (None, [], []), + (None, ["101"], []), + (None, ["102"], []), + (None, ["103"], []), + (None, ["101", "102"], []), + (None, ["101", "103"], []), + (None, ["102", "103"], []), + (None, ["101", "102", "103"], []), + # fmt: on + ], +) +def test_get_all__non_admin_permissions_filter( + db_session: Session, + user_id: t.Optional[int], + study_groups: t.Sequence[str], + expected_ids: t.List[str], +) -> None: + icache: Mock = Mock(spec=ICache) + repository = StudyMetadataRepository(cache_service=icache, session=db_session) + + user_1 = User(id=101, name="user1") + user_2 = User(id=102, name="user2") + user_3 = User(id=103, name="user3") + + group_1 = Group(id=101, name="group1") + group_2 = Group(id=102, name="group2") + group_3 = Group(id=103, name="group3") + + user_groups_mapping = {101: [group_2.id], 102: [group_1.id], 103: []} + + # create variant studies for user_1 and user_2 that are part of some groups + study_1 = VariantStudy(id=1, name="study-1", owner=user_1, groups=[group_1]) + study_2 = VariantStudy(id=2, name="study-2", owner=user_1, groups=[group_2]) + study_3 = VariantStudy(id=3, name="study-3", groups=[group_1]) + study_4 = VariantStudy(id=4, name="study-4", owner=user_2, groups=[group_1]) + study_5 = VariantStudy(id=5, name="study-5", owner=user_2, groups=[group_2]) + study_6 = VariantStudy(id=6, name="study-6", groups=[group_2]) + study_7 = VariantStudy(id=7, name="study-7", owner=user_1, groups=[group_1, group_2]) + study_8 = VariantStudy(id=8, name="study-8", owner=user_2, groups=[group_1, group_2]) + study_9 = VariantStudy(id=9, name="study-9", groups=[group_1, group_2]) + study_10 = VariantStudy(id=10, name="study-X10", owner=user_1) + study_11 = VariantStudy(id=11, name="study-X11", owner=user_2) + + # create variant studies with neither owner nor groups + study_12 = VariantStudy(id=12, name="study-X12") + study_13 = VariantStudy(id=13, name="study-X13", public_mode=PublicMode.READ) + study_14 = VariantStudy(id=14, name="study-X14", public_mode=PublicMode.EDIT) + study_15 = VariantStudy(id=15, name="study-X15", public_mode=PublicMode.EXECUTE) + study_16 = VariantStudy(id=16, name="study-X16", public_mode=PublicMode.FULL) + + # create raw studies for user_1 and user_2 that are part of some groups + study_17 = RawStudy(id=17, name="study-X17", owner=user_1, groups=[group_1]) + study_18 = RawStudy(id=18, name="study-X18", owner=user_1, groups=[group_2]) + study_19 = RawStudy(id=19, name="study-X19", groups=[group_1]) + study_20 = RawStudy(id=20, name="study-X20", owner=user_2, groups=[group_1]) + study_21 = RawStudy(id=21, name="study-X21", owner=user_2, groups=[group_2]) + study_22 = RawStudy(id=22, name="study-X22", groups=[group_2]) + study_23 = RawStudy(id=23, name="study-X23", owner=user_1, groups=[group_1, group_2]) + study_24 = RawStudy(id=24, name="study-X24", owner=user_2, groups=[group_1, group_2]) + study_25 = RawStudy(id=25, name="study-X25", groups=[group_1, group_2]) + study_26 = RawStudy(id=26, name="study-X26", owner=user_1) + study_27 = RawStudy(id=27, name="study-X27", owner=user_2) + + # create raw studies with neither owner nor groups + study_28 = RawStudy(id=28, name="study-X28") + study_29 = RawStudy(id=29, name="study-X29", public_mode=PublicMode.READ) + study_30 = RawStudy(id=30, name="study-X30", public_mode=PublicMode.EDIT) + study_31 = RawStudy(id=31, name="study-X31", public_mode=PublicMode.EXECUTE) + study_32 = RawStudy(id=32, name="study-X32", public_mode=PublicMode.FULL) + + # create studies for user_3 that is not part of any group + study_33 = VariantStudy(id=33, name="study-X33", owner=user_3, groups=[group_1]) + study_34 = RawStudy(id=34, name="study-X34", owner=user_3, groups=[group_2]) + study_35 = VariantStudy(id=35, name="study-X35", owner=user_3) + study_36 = RawStudy(id=36, name="study-X36", owner=user_3) + + # create studies for group_3 that has no user + study_37 = VariantStudy(id=37, name="study-X37", groups=[group_3]) + study_38 = RawStudy(id=38, name="study-X38", groups=[group_3]) + + db_session.add_all([user_1, user_2, user_3, group_1, group_2, group_3]) + db_session.add_all( + [ + # fmt: off + study_1, study_2, study_3, study_4, study_5, study_6, study_7, study_8, study_9, study_10, + study_11, study_12, study_13, study_14, study_15, study_16, study_17, study_18, study_19, study_20, + study_21, study_22, study_23, study_24, study_25, study_26, study_27, study_28, study_29, study_30, + study_31, study_32, study_33, study_34, study_35, study_36, study_37, study_38, + # fmt: on + ] + ) + db_session.commit() + + access_permissions = ( + AccessPermissions(user_id=user_id, user_groups=user_groups_mapping.get(user_id)) + if user_id + else AccessPermissions() + ) + study_filter = ( + StudyFilter(groups=study_groups, access_permissions=access_permissions) + if study_groups + else StudyFilter(access_permissions=access_permissions) + ) + + # use the db recorder to check that: + # 1- retrieving all studies requires only 1 query + # 2- accessing studies attributes does not require additional queries to db + # 3- having an exact total of queries equals to 1 + with DBStatementRecorder(db_session.bind) as db_recorder: + all_studies = repository.get_all(study_filter=study_filter) _ = [s.owner for s in all_studies] _ = [s.groups for s in all_studies] _ = [s.additional_data for s in all_studies] @@ -658,4 +998,244 @@ def test_repository_get_all__study_tags_filter( assert len(db_recorder.sql_statements) == 1, str(db_recorder) if expected_ids is not None: - assert {s.id for s in all_studies} == expected_ids + assert sorted((s.id for s in all_studies), key=int) == expected_ids + + # test pagination + with DBStatementRecorder(db_session.bind) as db_recorder: + all_studies = repository.get_all(study_filter=study_filter, pagination=StudyPagination(page_nb=1, page_size=2)) + assert len(all_studies) == max(0, min(len(expected_ids) - 2, 2)) + assert sorted((s.id for s in all_studies), key=int) == expected_ids[2:4] + assert len(db_recorder.sql_statements) == 1, str(db_recorder) + + +@pytest.mark.parametrize( + "is_admin, study_groups, expected_ids", + [ + # fmt: off + (True, [], [str(e) for e in range(1, 39)]), + (True, ["101"], ["1", "3", "4", "7", "8", "9", "17", "19", "20", "23", "24", "25", "33"]), + (True, ["102"], ["2", "5", "6", "7", "8", "9", "18", "21", "22", "23", "24", "25", "34"]), + (True, ["103"], ["37", "38"]), + (True, ["101", "102"], ["1", "2", "3", "4", "5", "6", "7", "8", "9", "17", "18", "19", + "20", "21", "22", "23", "24", "25", "33", "34"]), + (True, ["101", "103"], ["1", "3", "4", "7", "8", "9", "17", "19", "20", "23", "24", "25", "33", "37", "38"]), + (True, ["101", "102", "103"], ["1", "2", "3", "4", "5", "6", "7", "8", "9", "17", "18", + "19", "20", "21", "22", "23", "24", "25", "33", "34", "37", "38"]), + (False, [], []), + (False, ["101"], []), + (False, ["102"], []), + (False, ["103"], []), + (False, ["101", "102"], []), + (False, ["101", "103"], []), + (False, ["101", "102", "103"], []), + # fmt: on + ], +) +def test_get_all__admin_permissions_filter( + db_session: Session, + is_admin: bool, + study_groups: t.Sequence[str], + expected_ids: t.List[str], +) -> None: + icache: Mock = Mock(spec=ICache) + repository = StudyMetadataRepository(cache_service=icache, session=db_session) + user_1 = User(id=101, name="user1") + user_2 = User(id=102, name="user2") + user_3 = User(id=103, name="user3") + + group_1 = Group(id=101, name="group1") + group_2 = Group(id=102, name="group2") + group_3 = Group(id=103, name="group3") + + # create variant studies for user_1 and user_2 that are part of some groups + study_1 = VariantStudy(id=1, name="study-1", owner=user_1, groups=[group_1]) + study_2 = VariantStudy(id=2, name="study-2", owner=user_1, groups=[group_2]) + study_3 = VariantStudy(id=3, name="study-3", groups=[group_1]) + study_4 = VariantStudy(id=4, name="study-4", owner=user_2, groups=[group_1]) + study_5 = VariantStudy(id=5, name="study-5", owner=user_2, groups=[group_2]) + study_6 = VariantStudy(id=6, name="study-6", groups=[group_2]) + study_7 = VariantStudy(id=7, name="study-7", owner=user_1, groups=[group_1, group_2]) + study_8 = VariantStudy(id=8, name="study-8", owner=user_2, groups=[group_1, group_2]) + study_9 = VariantStudy(id=9, name="study-9", groups=[group_1, group_2]) + study_10 = VariantStudy(id=10, name="study-X10", owner=user_1) + study_11 = VariantStudy(id=11, name="study-X11", owner=user_2) + + # create variant studies with neither owner nor groups + study_12 = VariantStudy(id=12, name="study-X12") + study_13 = VariantStudy(id=13, name="study-X13", public_mode=PublicMode.READ) + study_14 = VariantStudy(id=14, name="study-X14", public_mode=PublicMode.EDIT) + study_15 = VariantStudy(id=15, name="study-X15", public_mode=PublicMode.EXECUTE) + study_16 = VariantStudy(id=16, name="study-X16", public_mode=PublicMode.FULL) + + # create raw studies for user_1 and user_2 that are part of some groups + study_17 = RawStudy(id=17, name="study-X17", owner=user_1, groups=[group_1]) + study_18 = RawStudy(id=18, name="study-X18", owner=user_1, groups=[group_2]) + study_19 = RawStudy(id=19, name="study-X19", groups=[group_1]) + study_20 = RawStudy(id=20, name="study-X20", owner=user_2, groups=[group_1]) + study_21 = RawStudy(id=21, name="study-X21", owner=user_2, groups=[group_2]) + study_22 = RawStudy(id=22, name="study-X22", groups=[group_2]) + study_23 = RawStudy(id=23, name="study-X23", owner=user_1, groups=[group_1, group_2]) + study_24 = RawStudy(id=24, name="study-X24", owner=user_2, groups=[group_1, group_2]) + study_25 = RawStudy(id=25, name="study-X25", groups=[group_1, group_2]) + study_26 = RawStudy(id=26, name="study-X26", owner=user_1) + study_27 = RawStudy(id=27, name="study-X27", owner=user_2) + + # create raw studies with neither owner nor groups + study_28 = RawStudy(id=28, name="study-X28") + study_29 = RawStudy(id=29, name="study-X29", public_mode=PublicMode.READ) + study_30 = RawStudy(id=30, name="study-X30", public_mode=PublicMode.EDIT) + study_31 = RawStudy(id=31, name="study-X31", public_mode=PublicMode.EXECUTE) + study_32 = RawStudy(id=32, name="study-X32", public_mode=PublicMode.FULL) + + # create studies for user_3 that is not part of any group + study_33 = VariantStudy(id=33, name="study-X33", owner=user_3, groups=[group_1]) + study_34 = RawStudy(id=34, name="study-X34", owner=user_3, groups=[group_2]) + study_35 = VariantStudy(id=35, name="study-X35", owner=user_3) + study_36 = RawStudy(id=36, name="study-X36", owner=user_3) + + # create studies for group_3 that has no user + study_37 = VariantStudy(id=37, name="study-X37", groups=[group_3]) + study_38 = RawStudy(id=38, name="study-X38", groups=[group_3]) + + db_session.add_all([user_1, user_2, user_3, group_1, group_2, group_3]) + db_session.add_all( + [ + # fmt: off + study_1, study_2, study_3, study_4, study_5, study_6, study_7, study_8, study_9, study_10, + study_11, study_12, study_13, study_14, study_15, study_16, study_17, study_18, study_19, study_20, + study_21, study_22, study_23, study_24, study_25, study_26, study_27, study_28, study_29, study_30, + study_31, study_32, study_33, study_34, study_35, study_36, study_37, study_38, + # fmt: on + ] + ) + db_session.commit() + + access_permissions = AccessPermissions(is_admin=is_admin) + + study_filter = ( + StudyFilter(groups=study_groups, access_permissions=access_permissions) + if study_groups + else StudyFilter(access_permissions=access_permissions) + ) + # use the db recorder to check that: + # 1- retrieving all studies requires only 1 query + # 2- accessing studies attributes does not require additional queries to db + # 3- having an exact total of queries equals to 1 + with DBStatementRecorder(db_session.bind) as db_recorder: + all_studies = repository.get_all(study_filter=study_filter) + _ = [s.owner for s in all_studies] + _ = [s.groups for s in all_studies] + _ = [s.additional_data for s in all_studies] + _ = [s.tags for s in all_studies] + assert len(db_recorder.sql_statements) == 1, str(db_recorder) + + if expected_ids is not None: + assert sorted((s.id for s in all_studies), key=int) == expected_ids + + # test pagination + with DBStatementRecorder(db_session.bind) as db_recorder: + all_studies = repository.get_all(study_filter=study_filter, pagination=StudyPagination(page_nb=1, page_size=2)) + assert len(all_studies) == max(0, min(len(expected_ids) - 2, 2)) + assert sorted((s.id for s in all_studies), key=int) == expected_ids[2:4] + assert len(db_recorder.sql_statements) == 1, str(db_recorder) + + +def test_update_tags( + db_session: Session, +) -> None: + icache: Mock = Mock(spec=ICache) + repository = StudyMetadataRepository(cache_service=icache, session=db_session) + + study_id = 1 + study = RawStudy(id=study_id, name=f"study-{study_id}", tags=[]) + db_session.add(study) + db_session.commit() + + # use the db recorder to check that: + # 1- finding existing tags requires 1 query + # 2- updating the study tags requires 4 queries (2 selects, 2 inserts) + # 3- deleting orphan tags requires 1 query + with DBStatementRecorder(db_session.bind) as db_recorder: + repository.update_tags(study, ["Tag1", "Tag2"]) + assert len(db_recorder.sql_statements) == 6, str(db_recorder) + + # Check that when we change the tags to ["TAG1", "Tag3"], + # "Tag1" is preserved, "Tag2" is deleted and "Tag3" is created + # 1- finding existing tags requires 1 query + # 2- updating the study tags requires 4 queries (2 selects, 2 inserts, 1 delete) + # 3- deleting orphan tags requires 1 query + with DBStatementRecorder(db_session.bind) as db_recorder: + repository.update_tags(study, ["TAG1", "Tag3"]) + assert len(db_recorder.sql_statements) == 7, str(db_recorder) + + # Check that only "Tag1" and "Tag3" are present in the database + tags = db_session.query(Tag).all() + assert {tag.label for tag in tags} == {"Tag1", "Tag3"} + + +@pytest.mark.parametrize( + "managed, study_ids, exists, expected_ids", + [ + (None, [], False, ["5", "6"]), + (None, [], True, ["1", "2", "3", "4", "7", "8"]), + (None, [], None, ["1", "2", "3", "4", "5", "6", "7", "8"]), + (None, [1, 3, 5, 7], False, ["5"]), + (None, [1, 3, 5, 7], True, ["1", "3", "7"]), + (None, [1, 3, 5, 7], None, ["1", "3", "5", "7"]), + (True, [], False, ["5"]), + (True, [], True, ["1", "2", "3", "4", "8"]), + (True, [], None, ["1", "2", "3", "4", "5", "8"]), + (True, [1, 3, 5, 7], False, ["5"]), + (True, [1, 3, 5, 7], True, ["1", "3"]), + (True, [1, 3, 5, 7], None, ["1", "3", "5"]), + (True, [2, 4, 6, 8], True, ["2", "4", "8"]), + (True, [2, 4, 6, 8], None, ["2", "4", "8"]), + (False, [], False, ["6"]), + (False, [], True, ["7"]), + (False, [], None, ["6", "7"]), + (False, [1, 3, 5, 7], False, []), + (False, [1, 3, 5, 7], True, ["7"]), + (False, [1, 3, 5, 7], None, ["7"]), + ], +) +def test_count_studies__general_case( + db_session: Session, + managed: t.Union[bool, None], + study_ids: t.Sequence[str], + exists: t.Union[bool, None], + expected_ids: t.List[str], +) -> None: + test_workspace = "test-repository" + icache: Mock = Mock(spec=ICache) + repository = StudyMetadataRepository(cache_service=icache, session=db_session) + + study_1 = VariantStudy(id=1, name="study-1") + study_2 = VariantStudy(id=2, name="study-2") + study_3 = VariantStudy(id=3, name="study-3") + study_4 = VariantStudy(id=4, name="study-4") + study_5 = RawStudy(id=5, name="study-5", missing=datetime.datetime.now(), workspace=DEFAULT_WORKSPACE_NAME) + study_6 = RawStudy(id=6, name="study-6", missing=datetime.datetime.now(), workspace=test_workspace) + study_7 = RawStudy(id=7, name="study-7", missing=None, workspace=test_workspace) + study_8 = RawStudy(id=8, name="study-8", missing=None, workspace=DEFAULT_WORKSPACE_NAME) + + db_session.add_all([study_1, study_2, study_3, study_4, study_5, study_6, study_7, study_8]) + db_session.commit() + + # use the db recorder to check that: + # 1- retrieving all studies requires only 1 query + # 2- accessing studies attributes does not require additional queries to db + # 3- having an exact total of queries equals to 1 + with DBStatementRecorder(db_session.bind) as db_recorder: + count = repository.count_studies( + study_filter=StudyFilter( + managed=managed, + study_ids=study_ids, + exists=exists, + access_permissions=AccessPermissions(is_admin=True), + ) + ) + assert len(db_recorder.sql_statements) == 1, str(db_recorder) + + # test that the expected studies are returned + if expected_ids is not None: + assert count == len(expected_ids) diff --git a/tests/variantstudy/assets/empty_study_810.zip b/tests/variantstudy/assets/empty_study_810.zip new file mode 100644 index 0000000000..5d354af139 Binary files /dev/null and b/tests/variantstudy/assets/empty_study_810.zip differ diff --git a/tests/variantstudy/assets/empty_study_840.zip b/tests/variantstudy/assets/empty_study_840.zip new file mode 100644 index 0000000000..6954ff5841 Binary files /dev/null and b/tests/variantstudy/assets/empty_study_840.zip differ diff --git a/tests/variantstudy/assets/empty_study_870.zip b/tests/variantstudy/assets/empty_study_870.zip new file mode 100644 index 0000000000..7838152994 Binary files /dev/null and b/tests/variantstudy/assets/empty_study_870.zip differ diff --git a/tests/variantstudy/conftest.py b/tests/variantstudy/conftest.py index f8dd8f2ebd..b08851b07b 100644 --- a/tests/variantstudy/conftest.py +++ b/tests/variantstudy/conftest.py @@ -8,6 +8,12 @@ import numpy.typing as npt import pytest +from antarest.study.storage.study_upgrader import get_current_version + +if t.TYPE_CHECKING: + # noinspection PyPackageRequirements + from _pytest.fixtures import SubRequest + from antarest.matrixstore.model import MatrixDTO from antarest.matrixstore.service import MatrixService from antarest.matrixstore.uri_resolver_service import UriResolverService @@ -90,6 +96,7 @@ def get_matrix_id(matrix: t.Union[t.List[t.List[float]], str]) -> str: matrix_service.get.side_effect = get matrix_service.exists.side_effect = exists matrix_service.delete.side_effect = delete + matrix_service.get_matrix_id.side_effect = get_matrix_id return matrix_service @@ -137,27 +144,32 @@ def command_factory_fixture(matrix_service: MatrixService) -> CommandFactory: @pytest.fixture(name="empty_study") -def empty_study_fixture(tmp_path: Path, matrix_service: MatrixService) -> FileStudy: +def empty_study_fixture(request: "SubRequest", tmp_path: Path, matrix_service: MatrixService) -> FileStudy: """ Fixture for creating an empty FileStudy object. Args: + request: pytest's request object. tmp_path: The temporary path for extracting the empty study. matrix_service: The MatrixService object. Returns: FileStudy: The empty FileStudy object. """ - empty_study_path: Path = ASSETS_DIR / "empty_study_720.zip" + zip_name = getattr(request, "param", "empty_study_720.zip") + empty_study_path: Path = ASSETS_DIR / zip_name empty_study_destination_path = tmp_path.joinpath("empty-study") with zipfile.ZipFile(empty_study_path, "r") as zip_empty_study: zip_empty_study.extractall(empty_study_destination_path) + # Detect the version of the study from `study.antares` file. + version = get_current_version(empty_study_destination_path) + config = FileStudyTreeConfig( study_path=empty_study_destination_path, path=empty_study_destination_path, study_id="", - version=720, + version=int(version), areas={}, sets={}, ) diff --git a/tests/variantstudy/model/command/test_create_area.py b/tests/variantstudy/model/command/test_create_area.py index 62e01aeba4..330067db56 100644 --- a/tests/variantstudy/model/command/test_create_area.py +++ b/tests/variantstudy/model/command/test_create_area.py @@ -3,7 +3,7 @@ import pytest -from antarest.study.storage.rawstudy.model.filesystem.config.model import ENR_MODELLING, transform_name_to_id +from antarest.study.storage.rawstudy.model.filesystem.config.model import EnrModelling, transform_name_to_id from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy from antarest.study.storage.variantstudy.business.command_reverter import CommandReverter from antarest.study.storage.variantstudy.model.command.create_area import CreateArea @@ -14,7 +14,7 @@ class TestCreateArea: @pytest.mark.parametrize("version", [600, 650, 810, 830, 860]) - @pytest.mark.parametrize("enr_modelling", list(ENR_MODELLING)) + @pytest.mark.parametrize("enr_modelling", list(EnrModelling)) def test_apply( self, empty_study: FileStudy, @@ -132,7 +132,7 @@ def test_apply( assert (study_path / "input" / "thermal" / "clusters" / area_id / "list.ini").exists() # Renewable Clusters - if version >= 810 and empty_study.config.enr_modelling == ENR_MODELLING.CLUSTERS.value: + if version >= 810 and empty_study.config.enr_modelling == EnrModelling.CLUSTERS.value: assert (study_path / "input" / "renewables" / "clusters" / area_id).is_dir() assert (study_path / "input" / "renewables" / "clusters" / area_id / "list.ini").exists() diff --git a/tests/variantstudy/model/command/test_create_renewables_cluster.py b/tests/variantstudy/model/command/test_create_renewables_cluster.py index ecec2fd882..51e553bcb8 100644 --- a/tests/variantstudy/model/command/test_create_renewables_cluster.py +++ b/tests/variantstudy/model/command/test_create_renewables_cluster.py @@ -1,10 +1,11 @@ import configparser import re +from unittest import mock import pytest from pydantic import ValidationError -from antarest.study.storage.rawstudy.model.filesystem.config.model import ENR_MODELLING, transform_name_to_id +from antarest.study.storage.rawstudy.model.filesystem.config.model import EnrModelling, transform_name_to_id from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy from antarest.study.storage.variantstudy.business.command_reverter import CommandReverter from antarest.study.storage.variantstudy.model.command.common import CommandName @@ -16,7 +17,8 @@ class TestCreateRenewablesCluster: - def test_init(self, command_context: CommandContext): + # noinspection SpellCheckingInspection + def test_init(self, command_context: CommandContext) -> None: cl = CreateRenewablesCluster( area_id="foo", cluster_name="Cluster1", @@ -34,12 +36,13 @@ def test_init(self, command_context: CommandContext): assert cl.cluster_name == "Cluster1" assert cl.parameters == {"group": "Solar Thermal", "nominalcapacity": "2400", "unitcount": "2"} - def test_validate_cluster_name(self, command_context: CommandContext): + def test_validate_cluster_name(self, command_context: CommandContext) -> None: with pytest.raises(ValidationError, match="cluster_name"): CreateRenewablesCluster(area_id="fr", cluster_name="%", command_context=command_context, parameters={}) - def test_apply(self, empty_study: FileStudy, command_context: CommandContext): - empty_study.config.enr_modelling = ENR_MODELLING.CLUSTERS.value + def test_apply(self, empty_study: FileStudy, command_context: CommandContext) -> None: + empty_study.config.enr_modelling = EnrModelling.CLUSTERS.value + empty_study.config.version = 810 study_path = empty_study.config.study_path area_name = "DE" area_id = transform_name_to_id(area_name, lower=True) @@ -107,7 +110,8 @@ def test_apply(self, empty_study: FileStudy, command_context: CommandContext): flags=re.IGNORECASE, ) - def test_to_dto(self, command_context: CommandContext): + # noinspection SpellCheckingInspection + def test_to_dto(self, command_context: CommandContext) -> None: command = CreateRenewablesCluster( area_id="foo", cluster_name="Cluster1", @@ -127,7 +131,7 @@ def test_to_dto(self, command_context: CommandContext): } -def test_match(command_context: CommandContext): +def test_match(command_context: CommandContext) -> None: base = CreateRenewablesCluster( area_id="foo", cluster_name="foo", @@ -159,23 +163,25 @@ def test_match(command_context: CommandContext): assert base.get_inner_matrices() == [] -def test_revert(command_context: CommandContext): +def test_revert(command_context: CommandContext) -> None: base = CreateRenewablesCluster( - area_id="foo", - cluster_name="foo", + area_id="area_foo", + cluster_name="cl1", parameters={}, command_context=command_context, ) - assert CommandReverter().revert(base, [], None) == [ + file_study = mock.MagicMock(spec=FileStudy) + revert_cmd = CommandReverter().revert(base, [], file_study) + assert revert_cmd == [ RemoveRenewablesCluster( - area_id="foo", - cluster_id="foo", + area_id="area_foo", + cluster_id="cl1", command_context=command_context, ) ] -def test_create_diff(command_context: CommandContext): +def test_create_diff(command_context: CommandContext) -> None: base = CreateRenewablesCluster( area_id="foo", cluster_name="foo", diff --git a/tests/variantstudy/model/command/test_manage_binding_constraints.py b/tests/variantstudy/model/command/test_manage_binding_constraints.py index c28b50b69d..d79f744960 100644 --- a/tests/variantstudy/model/command/test_manage_binding_constraints.py +++ b/tests/variantstudy/model/command/test_manage_binding_constraints.py @@ -1,17 +1,23 @@ from unittest.mock import Mock import numpy as np +import pytest from antarest.study.storage.rawstudy.ini_reader import IniReader -from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import BindingConstraintFrequency +from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import ( + BindingConstraintFrequency, + BindingConstraintOperator, +) from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy from antarest.study.storage.variantstudy.business.command_extractor import CommandExtractor from antarest.study.storage.variantstudy.business.command_reverter import CommandReverter -from antarest.study.storage.variantstudy.business.matrix_constants.binding_constraint.series import ( +from antarest.study.storage.variantstudy.business.matrix_constants.binding_constraint.series_after_v87 import ( + default_bc_weekly_daily as default_bc_weekly_daily_870, +) +from antarest.study.storage.variantstudy.business.matrix_constants.binding_constraint.series_before_v87 import ( default_bc_hourly, default_bc_weekly_daily, ) -from antarest.study.storage.variantstudy.model.command.common import BindingConstraintOperator from antarest.study.storage.variantstudy.model.command.create_area import CreateArea from antarest.study.storage.variantstudy.model.command.create_binding_constraint import CreateBindingConstraint from antarest.study.storage.variantstudy.model.command.create_cluster import CreateCluster @@ -24,41 +30,18 @@ # noinspection SpellCheckingInspection -def test_manage_binding_constraint( - empty_study: FileStudy, - command_context: CommandContext, -): +@pytest.mark.parametrize("empty_study", ["empty_study_720.zip", "empty_study_870.zip"], indirect=True) +def test_manage_binding_constraint(empty_study: FileStudy, command_context: CommandContext): study_path = empty_study.config.study_path area1 = "area1" area2 = "area2" cluster = "cluster" - CreateArea.parse_obj( - { - "area_name": area1, - "command_context": command_context, - } - ).apply(empty_study) - CreateArea.parse_obj( - { - "area_name": area2, - "command_context": command_context, - } - ).apply(empty_study) - CreateLink.parse_obj( - { - "area1": area1, - "area2": area2, - "command_context": command_context, - } - ).apply(empty_study) + CreateArea.parse_obj({"area_name": area1, "command_context": command_context}).apply(empty_study) + CreateArea.parse_obj({"area_name": area2, "command_context": command_context}).apply(empty_study) + CreateLink.parse_obj({"area1": area1, "area2": area2, "command_context": command_context}).apply(empty_study) CreateCluster.parse_obj( - { - "area_id": area1, - "cluster_name": cluster, - "parameters": {}, - "command_context": command_context, - } + {"area_id": area1, "cluster_name": cluster, "parameters": {}, "command_context": command_context} ).apply(empty_study) bind1_cmd = CreateBindingConstraint( @@ -83,14 +66,23 @@ def test_manage_binding_constraint( res2 = bind2_cmd.apply(empty_study) assert res2.status - bc1_matrix_path = study_path / "input/bindingconstraints/bd 1.txt.link" - bc2_matrix_path = study_path / "input/bindingconstraints/bd 2.txt.link" - assert bc1_matrix_path.exists() - assert bc2_matrix_path.exists() + if empty_study.config.version < 870: + matrix_links = ["bd 1.txt.link", "bd 2.txt.link"] + else: + matrix_links = [ + # fmt: off + "bd 1_lt.txt.link", "bd 1_eq.txt.link", "bd 1_gt.txt.link", + "bd 2_lt.txt.link", "bd 2_eq.txt.link", "bd 2_gt.txt.link", + # fmt: on + ] + for matrix_link in matrix_links: + link_path = study_path / f"input/bindingconstraints/{matrix_link}" + assert link_path.exists(), f"Missing matrix link: {matrix_link!r}" cfg_path = study_path / "input/bindingconstraints/bindingconstraints.ini" bd_config = IniReader().read(cfg_path) - assert bd_config.get("0") == { + + expected_bd_1 = { "name": "BD 1", "id": "bd 1", "enabled": True, @@ -99,51 +91,98 @@ def test_manage_binding_constraint( "operator": "less", "type": "hourly", } - assert bd_config.get("1") == { + expected_bd_2 = { "name": "BD 2", "id": "bd 2", "enabled": False, + "comments": "", "area1.cluster": 50.0, "operator": "both", "type": "daily", } + if empty_study.config.version >= 830: + expected_bd_1["filter-year-by-year"] = "" + expected_bd_1["filter-synthesis"] = "" + expected_bd_2["filter-year-by-year"] = "" + expected_bd_2["filter-synthesis"] = "" + if empty_study.config.version >= 870: + expected_bd_1["group"] = "default" + expected_bd_2["group"] = "default" + + assert bd_config.get("0") == expected_bd_1 + assert bd_config.get("1") == expected_bd_2 + + if empty_study.config.version < 870: + weekly_values = default_bc_weekly_daily.tolist() + values = weekly_values + less_term_matrix = None + greater_term_matrix = None + else: + weekly_values = default_bc_weekly_daily_870.tolist() + values = None + less_term_matrix = weekly_values + greater_term_matrix = weekly_values - weekly_values = default_bc_weekly_daily.tolist() bind_update = UpdateBindingConstraint( id="bd 1", enabled=False, time_step=BindingConstraintFrequency.WEEKLY, operator=BindingConstraintOperator.BOTH, coeffs={"area1%area2": [800, 30]}, - values=weekly_values, + values=values, + less_term_matrix=less_term_matrix, + greater_term_matrix=greater_term_matrix, command_context=command_context, ) res = bind_update.apply(empty_study) assert res.status bd_config = IniReader().read(cfg_path) - assert bd_config.get("0") == { + expected_bd_1 = { "name": "BD 1", "id": "bd 1", "enabled": False, + "comments": "Hello", # comments are not updated "area1%area2": "800.0%30", "operator": "both", "type": "weekly", } + if empty_study.config.version >= 830: + expected_bd_1["filter-year-by-year"] = "" + expected_bd_1["filter-synthesis"] = "" + if empty_study.config.version >= 870: + expected_bd_1["group"] = "default" + assert bd_config.get("0") == expected_bd_1 remove_bind = RemoveBindingConstraint(id="bd 1", command_context=command_context) res3 = remove_bind.apply(empty_study) assert res3.status - assert not bc1_matrix_path.exists() + + for matrix_link in matrix_links: + link_path = study_path / f"input/bindingconstraints/{matrix_link}" + if matrix_link.startswith("bd 1"): + assert not link_path.exists(), f"Matrix link not removed: {matrix_link!r}" + elif matrix_link.startswith("bd 2"): + assert link_path.exists(), f"Matrix link removed: {matrix_link!r}" + else: + raise NotImplementedError(f"Unexpected matrix link: {matrix_link!r}") + bd_config = IniReader().read(cfg_path) assert len(bd_config) == 1 - assert bd_config.get("0") == { + expected_bd_2 = { "name": "BD 2", "id": "bd 2", "enabled": False, "area1.cluster": 50.0, + "comments": "", "operator": "both", "type": "daily", } + if empty_study.config.version >= 830: + expected_bd_2["filter-year-by-year"] = "" + expected_bd_2["filter-synthesis"] = "" + if empty_study.config.version >= 870: + expected_bd_2["group"] = "default" + assert bd_config.get("0") == expected_bd_2 def test_match(command_context: CommandContext): @@ -326,9 +365,10 @@ def test_revert(command_context: CommandContext): enabled=True, time_step=BindingConstraintFrequency.HOURLY, operator=BindingConstraintOperator.EQUAL, + filter_year_by_year="", + filter_synthesis="", coeffs={"a": [0.3]}, values=hourly_matrix_id, - comments=None, command_context=command_context, ) ] @@ -350,13 +390,14 @@ def test_create_diff(command_context: CommandContext): ) values_b = np.random.rand(8784, 3).tolist() + matrix_b_id = command_context.matrix_service.create(values_b) other_match = CreateBindingConstraint( name="foo", enabled=True, time_step=BindingConstraintFrequency.HOURLY, operator=BindingConstraintOperator.EQUAL, coeffs={"b": [0.3]}, - values=values_b, + values=matrix_b_id, command_context=command_context, ) assert base.create_diff(other_match) == [ @@ -366,7 +407,7 @@ def test_create_diff(command_context: CommandContext): time_step=BindingConstraintFrequency.HOURLY, operator=BindingConstraintOperator.EQUAL, coeffs={"b": [0.3]}, - values=values_b, + values=matrix_b_id, command_context=command_context, ) ] diff --git a/tests/variantstudy/model/command/test_remove_area.py b/tests/variantstudy/model/command/test_remove_area.py index 3fb77082f2..90c19d34b9 100644 --- a/tests/variantstudy/model/command/test_remove_area.py +++ b/tests/variantstudy/model/command/test_remove_area.py @@ -1,10 +1,11 @@ import pytest -from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import BindingConstraintFrequency +from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import ( + BindingConstraintFrequency, + BindingConstraintOperator, +) from antarest.study.storage.rawstudy.model.filesystem.config.model import transform_name_to_id from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy -from antarest.study.storage.study_upgrader import upgrade_study -from antarest.study.storage.variantstudy.model.command.common import BindingConstraintOperator from antarest.study.storage.variantstudy.model.command.create_area import CreateArea from antarest.study.storage.variantstudy.model.command.create_binding_constraint import CreateBindingConstraint from antarest.study.storage.variantstudy.model.command.create_cluster import CreateCluster @@ -18,13 +19,8 @@ class TestRemoveArea: - @pytest.mark.parametrize("version", [810, 840]) - def test_apply( - self, - empty_study: FileStudy, - command_context: CommandContext, - version: int, - ): + @pytest.mark.parametrize("empty_study", ["empty_study_810.zip", "empty_study_840.zip"], indirect=True) + def test_apply(self, empty_study: FileStudy, command_context: CommandContext): # noinspection SpellCheckingInspection empty_study.tree.save( { @@ -72,10 +68,8 @@ def test_apply( ######################################################################################## - upgrade_study(empty_study.config.study_path, str(version)) - empty_study_cfg = empty_study.tree.get(depth=999) - if version >= 830: + if empty_study.config.version >= 830: empty_study_cfg["input"]["areas"][area_id]["adequacy_patch"] = { "adequacy-patch": {"adequacy-patch-mode": "outside"} } @@ -84,7 +78,6 @@ def test_apply( area_name2 = "Area2" area_id2 = transform_name_to_id(area_name2) - empty_study.config.version = version create_area_command: ICommand = CreateArea.parse_obj( { "area_name": area_name2, diff --git a/tests/variantstudy/model/command/test_remove_cluster.py b/tests/variantstudy/model/command/test_remove_cluster.py index 99333d811a..f0dd04f2b1 100644 --- a/tests/variantstudy/model/command/test_remove_cluster.py +++ b/tests/variantstudy/model/command/test_remove_cluster.py @@ -1,9 +1,13 @@ +import numpy as np +import pytest from checksumdir import dirhash -from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import BindingConstraintFrequency +from antarest.study.storage.rawstudy.model.filesystem.config.binding_constraint import ( + BindingConstraintFrequency, + BindingConstraintOperator, +) from antarest.study.storage.rawstudy.model.filesystem.config.model import transform_name_to_id from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy -from antarest.study.storage.variantstudy.model.command.common import BindingConstraintOperator from antarest.study.storage.variantstudy.model.command.create_area import CreateArea from antarest.study.storage.variantstudy.model.command.create_binding_constraint import CreateBindingConstraint from antarest.study.storage.variantstudy.model.command.create_cluster import CreateCluster @@ -13,6 +17,7 @@ class TestRemoveCluster: + @pytest.mark.parametrize("empty_study", ["empty_study_720.zip", "empty_study_870.zip"], indirect=True) def test_apply(self, empty_study: FileStudy, command_context: CommandContext): area_name = "Area_name" area_id = transform_name_to_id(area_name) @@ -39,6 +44,15 @@ def test_apply(self, empty_study: FileStudy, command_context: CommandContext): modulation=[[0]], ).apply(empty_study) + # Binding constraint 2nd member: array of shape (8784, 3) + array = np.random.rand(8784, 3) * 1000 + if empty_study.config.version < 870: + values = array.tolist() + less_term_matrix = None + else: + values = None + less_term_matrix = array.tolist() + bind1_cmd = CreateBindingConstraint( name="BD 1", time_step=BindingConstraintFrequency.HOURLY, @@ -48,6 +62,8 @@ def test_apply(self, empty_study: FileStudy, command_context: CommandContext): }, comments="Hello", command_context=command_context, + values=values, + less_term_matrix=less_term_matrix, ) output = bind1_cmd.apply(study_data=empty_study) assert output.status diff --git a/tests/variantstudy/model/command/test_remove_renewables_cluster.py b/tests/variantstudy/model/command/test_remove_renewables_cluster.py index 26eaa52837..42573e8b74 100644 --- a/tests/variantstudy/model/command/test_remove_renewables_cluster.py +++ b/tests/variantstudy/model/command/test_remove_renewables_cluster.py @@ -1,6 +1,6 @@ from checksumdir import dirhash -from antarest.study.storage.rawstudy.model.filesystem.config.model import ENR_MODELLING, transform_name_to_id +from antarest.study.storage.rawstudy.model.filesystem.config.model import EnrModelling, transform_name_to_id from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy from antarest.study.storage.variantstudy.model.command.create_area import CreateArea from antarest.study.storage.variantstudy.model.command.create_renewables_cluster import CreateRenewablesCluster @@ -11,7 +11,7 @@ class TestRemoveRenewablesCluster: def test_apply(self, empty_study: FileStudy, command_context: CommandContext): - empty_study.config.enr_modelling = ENR_MODELLING.CLUSTERS.value + empty_study.config.enr_modelling = EnrModelling.CLUSTERS.value empty_study.config.version = 810 area_name = "Area_name" area_id = transform_name_to_id(area_name) diff --git a/tests/variantstudy/model/test_variant_model.py b/tests/variantstudy/model/test_variant_model.py index 63ac7293b8..98c73b949f 100644 --- a/tests/variantstudy/model/test_variant_model.py +++ b/tests/variantstudy/model/test_variant_model.py @@ -12,10 +12,10 @@ from antarest.study.model import RawStudy, StudyAdditionalData from antarest.study.storage.rawstudy.raw_study_service import RawStudyService from antarest.study.storage.variantstudy.business.matrix_constants_generator import GeneratorMatrixConstants -from antarest.study.storage.variantstudy.model.model import CommandDTO, GenerationResultInfoDTO +from antarest.study.storage.variantstudy.model.model import CommandDTO from antarest.study.storage.variantstudy.snapshot_generator import SnapshotGenerator from antarest.study.storage.variantstudy.variant_study_service import VariantStudyService -from tests.helpers import with_db_context +from tests.helpers import AnyUUID, with_db_context class TestVariantStudyService: @@ -141,13 +141,33 @@ def test_commands_service( repository=variant_study_service.repository, ) results = generator.generate_snapshot(saved_id, jwt_user, denormalize=False) - assert results == GenerationResultInfoDTO( - success=True, - details=[ - ("create_area", True, "Area 'Yes' created"), - ("create_area", True, "Area 'No' created"), - ("create_link", True, "Link between 'no' and 'yes' created"), - ("create_cluster", True, "Thermal cluster 'cl1' added to area 'yes'."), + assert results.dict() == { + "success": True, + "details": [ + { + "id": AnyUUID(), + "name": "create_area", + "status": True, + "msg": "Area 'Yes' created", + }, + { + "id": AnyUUID(), + "name": "create_area", + "status": True, + "msg": "Area 'No' created", + }, + { + "id": AnyUUID(), + "name": "create_link", + "status": True, + "msg": "Link between 'no' and 'yes' created", + }, + { + "id": AnyUUID(), + "name": "create_cluster", + "status": True, + "msg": "Thermal cluster 'cl1' added to area 'yes'.", + }, ], - ) + } assert study.snapshot.id == study.id diff --git a/tests/variantstudy/test_command_factory.py b/tests/variantstudy/test_command_factory.py index 10e62dc036..5f9af93ee2 100644 --- a/tests/variantstudy/test_command_factory.py +++ b/tests/variantstudy/test_command_factory.py @@ -125,14 +125,7 @@ def setup_class(self): ), CommandDTO( action=CommandName.CREATE_BINDING_CONSTRAINT.value, - args={ - "name": "name", - "enabled": True, - "time_step": "hourly", - "operator": "equal", - "coeffs": {}, - "values": "values", - }, + args={"name": "name"}, ), CommandDTO( action=CommandName.CREATE_BINDING_CONSTRAINT.value, @@ -142,9 +135,9 @@ def setup_class(self): "enabled": True, "time_step": "hourly", "operator": "equal", - "coeffs": {}, "values": "values", - } + "group": "group_1", + }, ], ), CommandDTO( @@ -154,7 +147,6 @@ def setup_class(self): "enabled": True, "time_step": "hourly", "operator": "equal", - "coeffs": {}, "values": "values", }, ), @@ -166,7 +158,6 @@ def setup_class(self): "enabled": True, "time_step": "hourly", "operator": "equal", - "coeffs": {}, } ], ), @@ -411,25 +402,27 @@ def get_matrix_id(matrix: str) -> str: command_factory = CommandFactory( generator_matrix_constants=Mock(spec=GeneratorMatrixConstants), - matrix_service=Mock(spec=MatrixService), + matrix_service=Mock(spec=MatrixService, get_matrix_id=get_matrix_id), patch_service=Mock(spec=PatchService), ) commands = command_factory.to_command(command_dto=command_dto) if isinstance(command_dto.args, dict): - exp_action_args_list = [(command_dto.action, command_dto.args)] + exp_action_args_list = [(command_dto.action, command_dto.args, command_dto.version)] else: - exp_action_args_list = [(command_dto.action, args) for args in command_dto.args] + exp_action_args_list = [(command_dto.action, args, command_dto.version) for args in command_dto.args] actual_cmd: ICommand - for actual_cmd, exp_action_args in itertools.zip_longest(commands, exp_action_args_list): - assert actual_cmd is not None, f"Missing action/args for {exp_action_args=}" - assert exp_action_args is not None, f"Missing command for {actual_cmd=}" - expected_action, expected_args = exp_action_args + for actual_cmd, exp_action_args_version in itertools.zip_longest(commands, exp_action_args_list): + assert actual_cmd is not None, f"Missing action/args for {exp_action_args_version=}" + assert exp_action_args_version is not None, f"Missing command for {actual_cmd=}" + expected_action, expected_args, expected_version = exp_action_args_version actual_dto = actual_cmd.to_dto() actual_args = {k: v for k, v in actual_dto.args.items() if v is not None} + actual_version = actual_dto.version assert actual_dto.action == expected_action assert actual_args == expected_args + assert actual_version == expected_version self.command_class_set.discard(type(commands[0]).__name__) diff --git a/webapp/.eslintrc.cjs b/webapp/.eslintrc.cjs index bd9d45c683..c39a0165bc 100644 --- a/webapp/.eslintrc.cjs +++ b/webapp/.eslintrc.cjs @@ -11,12 +11,14 @@ module.exports = { "plugin:react/recommended", "plugin:react/jsx-runtime", "plugin:react-hooks/recommended", + "plugin:jsdoc/recommended-typescript", "plugin:prettier/recommended", ], plugins: ["react-refresh"], ignorePatterns: ["dist", ".eslintrc.cjs"], parser: "@typescript-eslint/parser", parserOptions: { + // `ecmaVersion` is automatically sets by `esXXXX` in `env` sourceType: "module", project: ["./tsconfig.json", "./tsconfig.node.json"], tsconfigRootDir: __dirname, @@ -41,6 +43,12 @@ module.exports = { ], }, ], + curly: "error", + "jsdoc/no-defaults": "off", + "jsdoc/require-hyphen-before-param-description": "warn", + "jsdoc/require-jsdoc": "off", + "jsdoc/tag-lines": ["warn", "any", { "startLines": 1 }], // Expected 1 line after block description + "no-console": "error", "no-param-reassign": [ "error", { @@ -65,6 +73,9 @@ module.exports = { "warn", { allowConstantExport: true }, ], + "react/hook-use-state": "error", "react/prop-types": "off", + "react/self-closing-comp": "error", + "require-await": "warn", // TODO: switch to "error" when the quantity of warning will be low }, }; diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 58ecdf282c..10711529c7 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -1,12 +1,12 @@ { "name": "antares-web", - "version": "2.16.8", + "version": "2.17", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "antares-web", - "version": "2.16.8", + "version": "2.17", "dependencies": { "@emotion/react": "11.11.1", "@emotion/styled": "11.11.0", @@ -92,6 +92,7 @@ "@vitejs/plugin-react-swc": "3.5.0", "eslint": "8.55.0", "eslint-config-prettier": "9.0.0", + "eslint-plugin-jsdoc": "48.2.0", "eslint-plugin-prettier": "5.0.0", "eslint-plugin-react": "7.33.2", "eslint-plugin-react-hooks": "4.6.0", @@ -479,6 +480,20 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, + "node_modules/@es-joy/jsdoccomment": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.42.0.tgz", + "integrity": "sha512-R1w57YlVA6+YE01wch3GPYn6bCsrOV3YW/5oGGE2tmX6JcL9Nr+b5IikrjMPF+v9CV3ay+obImEdsDhovhJrzw==", + "dev": true, + "dependencies": { + "comment-parser": "1.4.1", + "esquery": "^1.5.0", + "jsdoc-type-pratt-parser": "~4.0.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.19.12", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", @@ -3951,6 +3966,15 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/are-docs-informative": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", + "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -4287,6 +4311,18 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/call-bind": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", @@ -4501,6 +4537,15 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, + "node_modules/comment-parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", + "dev": true, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -5578,6 +5623,29 @@ "eslint": ">=7.0.0" } }, + "node_modules/eslint-plugin-jsdoc": { + "version": "48.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.0.tgz", + "integrity": "sha512-O2B1XLBJnUCRkggFzUQ+PBYJDit8iAgXdlu8ucolqGrbmOWPvttZQZX8d1sC0MbqDMSLs8SHSQxaNPRY1RQREg==", + "dev": true, + "dependencies": { + "@es-joy/jsdoccomment": "~0.42.0", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.1", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.5.0", + "is-builtin-module": "^3.2.1", + "semver": "^7.6.0", + "spdx-expression-parse": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, "node_modules/eslint-plugin-prettier": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.0.tgz", @@ -7180,6 +7248,21 @@ "resolved": "https://registry.npmjs.org/is-browser/-/is-browser-2.1.0.tgz", "integrity": "sha512-F5rTJxDQ2sW81fcfOR1GnCXT6sVJC104fCyfj+mjpwNEwaPYSn5fte5jiHmBg3DHsIoL/l8Kvw5VN5SsTRcRFQ==" }, + "node_modules/is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dev": true, + "dependencies": { + "builtin-modules": "^3.3.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -7609,6 +7692,15 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsdoc-type-pratt-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", + "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", + "dev": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -9999,9 +10091,9 @@ } }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -10211,6 +10303,28 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", + "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", + "dev": true + }, "node_modules/split.js": { "version": "1.6.5", "resolved": "https://registry.npmjs.org/split.js/-/split.js-1.6.5.tgz", diff --git a/webapp/package.json b/webapp/package.json index 7c9677bb5c..106345bf84 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -1,6 +1,6 @@ { "name": "antares-web", - "version": "2.16.8", + "version": "2.17", "private": true, "type": "module", "scripts": { @@ -95,6 +95,7 @@ "@vitejs/plugin-react-swc": "3.5.0", "eslint": "8.55.0", "eslint-config-prettier": "9.0.0", + "eslint-plugin-jsdoc": "48.2.0", "eslint-plugin-prettier": "5.0.0", "eslint-plugin-react": "7.33.2", "eslint-plugin-react-hooks": "4.6.0", diff --git a/webapp/public/locales/en/main.json b/webapp/public/locales/en/main.json index bac71c5489..942d4630a9 100644 --- a/webapp/public/locales/en/main.json +++ b/webapp/public/locales/en/main.json @@ -5,6 +5,7 @@ "global.versions": "Versions", "global.reset": "Reset", "global.delete": "Delete", + "global.delete.all": "Delete all", "global.view": "View", "global.archive": "Archive", "global.unarchive": "Unarchive", @@ -31,6 +32,8 @@ "global.open": "Open", "global.name": "Name", "global.import": "Import", + "global.import.fromFile": "From a file", + "global.import.fromDatabase": "From database", "global.importHint": "Click or drag and drop here", "global.launch": "Launch", "global.jobs": "Jobs", @@ -47,6 +50,7 @@ "global.emptyString": "Empty string", "global.edit": "Edit", "global.download": "Download", + "global.download.error": "Download failed", "global.generate": "Generate", "global.user": "User", "global.users": "Users", @@ -72,6 +76,7 @@ "global.time.weekly": "Weekly", "global.time.monthly": "Monthly", "global.time.annual": "Annual", + "global.update.success": "Update successful", "global.errorLogs": "Error logs", "global.error.emptyName": "Name cannot be empty", "global.error.failedtoretrievejobs": "Failed to retrieve job information", @@ -384,11 +389,10 @@ "study.configuration.advancedParameters.simulationCores": "Simulation cores", "study.configuration.advancedParameters.renewableGenerationModeling": "Renewable generation modeling", "study.configuration.economicOpt": "Economic Opt.", - "study.configuration.geographicTrimmingAreas": "Geographic Trimming (areas)", - "study.configuration.geographicTrimmingLinks": "Geographic Trimming (links)", + "study.configuration.geographicTrimmingAreas": "Geographic Trimming (Areas)", + "study.configuration.geographicTrimmingLinks": "Geographic Trimming (Links)", + "study.configuration.geographicTrimmingBindingConstraints": "Geographic Trimming (Binding Constraints)", "study.modelization.properties": "Properties", - "study.modelization.properties.posX": "Position X", - "study.modelization.properties.posY": "Position Y", "study.modelization.properties.energyCost": "Energy cost (€/Wh)", "study.modelization.properties.unsupplied": "Unsupplied", "study.modelization.properties.spilled": "Spilled", @@ -499,9 +503,13 @@ "study.modelization.bindingConst.operator.both": "< and >", "study.modelization.bindingConst.enabled": "Enabled", "study.modelization.bindingConst.newBindingConst": "New binding constraint", - "study.modelization.bindingConst.constraintTerm": "Constraint term", + "study.modelization.bindingConst.constraintTerm": "Constraint terms", + "study.modelization.bindingConst.timeSeries": "Time series", + "study.modelization.bindingConst.timeSeries.less": "Less", + "study.modelization.bindingConst.timeSeries.equal": "Equal", + "study.modelization.bindingConst.timeSeries.greater": "Greater", "study.modelization.bindingConst.newConstraintTerm": "New constraint term", - "study.modelization.bindingConst.addConstraintTerm": "Add constraint term", + "study.modelization.bindingConst.createConstraintTerm": "Add constraint term", "study.modelization.bindingConst.weight": "Weight", "study.modelization.bindingConst.offset": "Offset", "study.modelization.bindingConst.question.deleteConstraintTerm": "Are you sure you want to delete this constraint term?", @@ -514,7 +522,7 @@ "study.results.display": "Display", "study.results.temporality": "Temporality", "study.results.noData": "No data available", - "study.error.addConstraintTerm": "Failed to add constraint term", + "study.error.createConstraintTerm": "Failed to add constraint term", "study.error.missingData": "Error: {{0}} and/or {{1}} is missing", "study.error.termAlreadyExist": "This term already exist", "study.error.addCluster": "Failed to add cluster", @@ -523,7 +531,7 @@ "study.error.form.clusterName": "Cluster name already exist", "study.error.deleteConstraintTerm": "Failed to delete constraint term", "study.error.updateConstraintTerm": "Failed to update constraint term", - "study.success.addConstraintTerm": "Constraint term added successfully", + "study.success.createConstraintTerm": "Constraint term added successfully", "study.success.addBindingConst": "Binding constraint created successfully", "study.success.deleteConstraint": "Binding constraint deleted successfully", "study.success.addCluster": "Cluster added successfully", @@ -723,5 +731,11 @@ "results.error.jobs": "Failed to retrieve study launch jobs", "results.error.outputs": "Failed to retrieve study output list", "results.noOutputs": "No outputs", - "results.question.deleteOutput": "Are you sure you want to delete the output {{outputname}}?" + "results.question.deleteOutput": "Are you sure you want to delete the output {{outputname}}?", + "tableMode.type.areas": "Areas", + "tableMode.type.links": "Links", + "tableMode.type.thermals": "Thermals", + "tableMode.type.renewables": "Renewables", + "tableMode.type.st-storages": "Short-Term Storages", + "tableMode.type.binding-constraints": "Binding Constraints" } diff --git a/webapp/public/locales/fr/main.json b/webapp/public/locales/fr/main.json index d3b5e8b512..5e4d02b567 100644 --- a/webapp/public/locales/fr/main.json +++ b/webapp/public/locales/fr/main.json @@ -5,6 +5,7 @@ "global.versions": "Versions", "global.reset": "Réinitialiser", "global.delete": "Supprimer", + "global.delete.all": "Supprimer tout", "global.view": "Voir", "global.archive": "Archiver", "global.unarchive": "Désarchiver", @@ -31,6 +32,8 @@ "global.open": "Ouvrir", "global.name": "Nom", "global.import": "Importer", + "global.import.fromFile": "Depuis un fichier", + "global.import.fromDatabase": "Depuis la base de donnée", "global.importHint": "Cliquer ou glisser ici", "global.launch": "Lancer", "global.jobs": "Tâches", @@ -47,6 +50,7 @@ "global.emptyString": "Chaine de caractères vide", "global.edit": "Editer", "global.download": "Télécharger", + "global.download.error": "Le téléchargement a échoué", "global.generate": "Générer", "global.user": "Utilisateur", "global.users": "Utilisateurs", @@ -72,6 +76,7 @@ "global.time.weekly": "Hebdomadaire", "global.time.monthly": "Mensuel", "global.time.annual": "Annuel", + "global.update.success": "Mise à jour réussie", "global.errorLogs": "Logs d'erreurs", "global.error.emptyName": "Le nom ne peut pas être vide", "global.error.failedtoretrievejobs": "Échec de la récupération des tâches", @@ -386,9 +391,8 @@ "study.configuration.economicOpt": "Options économiques", "study.configuration.geographicTrimmingAreas": "Filtre géographique (zones)", "study.configuration.geographicTrimmingLinks": "Filtre géographique (liens)", + "study.configuration.geographicTrimmingBindingConstraints": "Filtre géographique (contraintes couplantes)", "study.modelization.properties": "Propriétés", - "study.modelization.properties.posX": "Position X", - "study.modelization.properties.posY": "Position Y", "study.modelization.properties.energyCost": "Coût de l'énergie", "study.modelization.properties.unsupplied": "Non distribuée", "study.modelization.properties.spilled": "Non évacuée", @@ -499,9 +503,13 @@ "study.modelization.bindingConst.operator.both": "< and >", "study.modelization.bindingConst.enabled": "Activé", "study.modelization.bindingConst.newBindingConst": "Nouvelle contrainte couplante", - "study.modelization.bindingConst.constraintTerm": "Termes de contraintes", + "study.modelization.bindingConst.constraintTerm": "Termes de la contrainte", + "study.modelization.bindingConst.timeSeries": "Séries temporelles", + "study.modelization.bindingConst.timeSeries.less": "Inférieur", + "study.modelization.bindingConst.timeSeries.equal": "Égal", + "study.modelization.bindingConst.timeSeries.greater": "Supérieur", "study.modelization.bindingConst.newConstraintTerm": "Nouveau terme", - "study.modelization.bindingConst.addConstraintTerm": "Ajouter un terme", + "study.modelization.bindingConst.createConstraintTerm": "Ajouter un terme", "study.modelization.bindingConst.weight": "Poids", "study.modelization.bindingConst.offset": "Décalage", "study.modelization.bindingConst.question.deleteConstraintTerm": "Êtes-vous sûr de vouloir supprimer ce terme ?", @@ -514,7 +522,7 @@ "study.results.display": "Affichage", "study.results.temporality": "Temporalité", "study.results.noData": "Aucune donnée disponible", - "study.error.addConstraintTerm": "Échec lors de l'ajout du nouveau terme", + "study.error.createConstraintTerm": "Échec lors de l'ajout du nouveau terme", "study.error.missingData": "Erreur: {{0}} et/ou {{1}} est manquante", "study.error.termAlreadyExist": "Ce terme existe déjà", "study.error.addCluster": "Échec lors de la création du cluster", @@ -523,7 +531,7 @@ "study.error.form.clusterName": "Ce cluster existe déjà", "study.error.deleteConstraintTerm": "Échec lors de la suppression du terme", "study.error.updateConstraintTerm": "Erreur lors de la modification du terme", - "study.success.addConstraintTerm": "Nouveau terme ajouté avec succès", + "study.success.createConstraintTerm": "Nouveau terme ajouté avec succès", "study.success.addBindingConst": "Contrainte couplante créé avec succès", "study.success.deleteConstraint": "Contrainte couplante supprimée avec succès", "study.success.addCluster": "Cluster créé avec succès", @@ -723,5 +731,11 @@ "results.error.jobs": "Erreur lors de la récupération des tâches de lancement", "results.error.outputs": "Erreur lors de la récupération des sorties de l'étude", "results.noOutputs": "Aucune sorties", - "results.question.deleteOutput": "Êtes-vous sûr de vouloir supprimer le résultat de simulation {{outputname}} ?" + "results.question.deleteOutput": "Êtes-vous sûr de vouloir supprimer le résultat de simulation {{outputname}} ?", + "tableMode.type.areas": "Zones", + "tableMode.type.links": "Liens", + "tableMode.type.thermals": "Thermiques", + "tableMode.type.renewables": "Renouvelables", + "tableMode.type.st-storages": "Stockages court terme", + "tableMode.type.binding-constraints": "Contraintes couplantes" } diff --git a/webapp/src/components/App/Data/DatasetCreationDialog.tsx b/webapp/src/components/App/Data/DatasetCreationDialog.tsx index 41304025a2..c10b1eaaf4 100644 --- a/webapp/src/components/App/Data/DatasetCreationDialog.tsx +++ b/webapp/src/components/App/Data/DatasetCreationDialog.tsx @@ -50,9 +50,9 @@ function DatasetCreationDialog(props: PropTypes) { const [name, setName] = useState(""); const [isJson, setIsJson] = useState(false); const [uploadProgress, setUploadProgress] = useState(0); - const [currentFile, setFile] = useState(); + const [currentFile, setCurrentFile] = useState(); const [importing, setImporting] = useState(false); - const [publicStatus, setPublic] = useState(false); + const [publicStatus, setPublicStatus] = useState(false); const onSave = async () => { let closeModal = true; @@ -93,7 +93,7 @@ function DatasetCreationDialog(props: PropTypes) { const onUpload = (e: ChangeEvent) => { const { target } = e; if (target && target.files && target.files.length === 1) { - setFile(target.files[0]); + setCurrentFile(target.files[0]); } }; @@ -116,7 +116,7 @@ function DatasetCreationDialog(props: PropTypes) { if (data) { setSelectedGroupList(data.groups); - setPublic(data.public); + setPublicStatus(data.public); setName(data.name); } } catch (e) { @@ -249,7 +249,7 @@ function DatasetCreationDialog(props: PropTypes) { {t("global.public")} setPublic(!publicStatus)} + onChange={() => setPublicStatus(!publicStatus)} inputProps={{ "aria-label": "primary checkbox" }} /> diff --git a/webapp/src/components/App/Data/MatrixDialog.tsx b/webapp/src/components/App/Data/MatrixDialog.tsx index ddd7a59b85..df2b14ab99 100644 --- a/webapp/src/components/App/Data/MatrixDialog.tsx +++ b/webapp/src/components/App/Data/MatrixDialog.tsx @@ -17,7 +17,7 @@ function MatrixDialog(props: PropTypes) { const [t] = useTranslation(); const enqueueErrorSnackbar = useEnqueueErrorSnackbar(); const [loading, setLoading] = useState(false); - const [matrix, setCurrentMatrix] = useState({ + const [matrix, setMatrix] = useState({ index: [], columns: [], data: [], @@ -34,7 +34,7 @@ function MatrixDialog(props: PropTypes) { columns: matrix ? res.columns : [], data: matrix ? res.data : [], }; - setCurrentMatrix(matrixContent); + setMatrix(matrixContent); } } catch (error) { enqueueErrorSnackbar(t("data.error.matrix"), error as AxiosError); @@ -44,7 +44,7 @@ function MatrixDialog(props: PropTypes) { }; init(); return () => { - setCurrentMatrix({ index: [], columns: [], data: [] }); + setMatrix({ index: [], columns: [], data: [] }); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [enqueueErrorSnackbar, matrixInfo, t]); diff --git a/webapp/src/components/App/Settings/Groups/dialog/GroupFormDialog/GroupForm.tsx b/webapp/src/components/App/Settings/Groups/dialog/GroupFormDialog/GroupForm.tsx index e17dee147b..39e8e26ca4 100644 --- a/webapp/src/components/App/Settings/Groups/dialog/GroupFormDialog/GroupForm.tsx +++ b/webapp/src/components/App/Settings/Groups/dialog/GroupFormDialog/GroupForm.tsx @@ -115,6 +115,7 @@ function GroupForm(props: UseFormReturnPlus) { validateString(v, { existingValues: existingGroups, excludedValues: RESERVED_GROUP_NAMES, + editedValue: defaultValues?.name, // prevent false duplicates on update form }), })} /> diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/AdequacyPatch/index.tsx b/webapp/src/components/App/Singlestudy/explore/Configuration/AdequacyPatch/index.tsx index 9e301154bd..9793e24395 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/AdequacyPatch/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/AdequacyPatch/index.tsx @@ -53,7 +53,7 @@ function AdequacyPatch() { content: ( ), diff --git a/webapp/src/components/App/Singlestudy/explore/Configuration/index.tsx b/webapp/src/components/App/Singlestudy/explore/Configuration/index.tsx index eb9550e2bb..fd649e9e7d 100644 --- a/webapp/src/components/App/Singlestudy/explore/Configuration/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Configuration/index.tsx @@ -31,6 +31,10 @@ function Configuration() { { id: 5, name: t("study.configuration.economicOpt") }, { id: 6, name: t("study.configuration.geographicTrimmingAreas") }, { id: 7, name: t("study.configuration.geographicTrimmingLinks") }, + { + id: 8, + name: t("study.configuration.geographicTrimmingBindingConstraints"), + }, ].filter(Boolean), [study.version, t], ); @@ -63,7 +67,7 @@ function Configuration() { () => ( ( ), @@ -91,7 +95,17 @@ function Configuration() { () => ( + ), + ], + [ + R.equals(8), + () => ( + ), diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Json.tsx b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Json.tsx index 334fa84638..3923ce319a 100644 --- a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Json.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Json.tsx @@ -22,7 +22,7 @@ function Json({ path, studyId }: Props) { const { enqueueSnackbar } = useSnackbar(); const enqueueErrorSnackbar = useEnqueueErrorSnackbar(); const [jsonData, setJsonData] = useState(null); - const [isSaveAllowed, setSaveAllowed] = useState(false); + const [isSaveAllowed, setIsSaveAllowed] = useState(false); const res = usePromiseWithSnackbarError( () => getStudyData(studyId, path, -1), @@ -34,7 +34,7 @@ function Json({ path, studyId }: Props) { // Reset save button when path changes useUpdateEffect(() => { - setSaveAllowed(false); + setIsSaveAllowed(false); }, [studyId, path]); //////////////////////////////////////////////////////////////// @@ -48,7 +48,7 @@ function Json({ path, studyId }: Props) { enqueueSnackbar(t("studies.success.saveData"), { variant: "success", }); - setSaveAllowed(false); + setIsSaveAllowed(false); } catch (e) { enqueueErrorSnackbar(t("studies.error.saveData"), e as AxiosError); } @@ -57,7 +57,7 @@ function Json({ path, studyId }: Props) { const handleJsonChange = (newJson: string) => { setJsonData(newJson); - setSaveAllowed(true); + setIsSaveAllowed(true); }; //////////////////////////////////////////////////////////////// diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/utils.ts b/webapp/src/components/App/Singlestudy/explore/Debug/utils.ts index e97f0e00a7..a6e3798806 100644 --- a/webapp/src/components/App/Singlestudy/explore/Debug/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Debug/utils.ts @@ -22,9 +22,7 @@ export type TreeData = Record | string; // Utils //////////////////////////////////////////////////////////////// -/** - * Maps file types and folder to their corresponding icon components. - */ +//Maps file types and folder to their corresponding icon components. const iconByFileType: Record = { matrix: DatasetIcon, json: DataObjectIcon, @@ -34,8 +32,9 @@ const iconByFileType: Record = { /** * Gets the icon component for a given file type or folder. - * @param {FileType | "folder"} type - The type of the file or "folder". - * @returns {SvgIconComponent} The corresponding icon component. + * + * @param type - The type of the file or "folder". + * @returns The corresponding icon component. */ export const getFileIcon = (type: FileType | "folder"): SvgIconComponent => { return iconByFileType[type] || TextSnippetIcon; @@ -43,8 +42,9 @@ export const getFileIcon = (type: FileType | "folder"): SvgIconComponent => { /** * Determines the file type based on the tree data. - * @param {TreeData} treeData - The data of the tree item. - * @returns {FileType | "folder"} The determined file type or "folder". + * + * @param treeData - The data of the tree item. + * @returns The determined file type or "folder". */ export const determineFileType = (treeData: TreeData): FileType | "folder" => { if (typeof treeData === "string") { @@ -63,8 +63,9 @@ export const determineFileType = (treeData: TreeData): FileType | "folder" => { /** * Filters out specific keys from the tree data. - * @param {TreeData} data - The original tree data. - * @returns {TreeData} The filtered tree data. + * + * @param data - The original tree data. + * @returns The filtered tree data. */ export const filterTreeData = (data: TreeData): TreeData => { const excludedKeys = new Set(["Desktop", "study", "logs"]); diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/index.tsx index 289913bcbe..0baab19ab8 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/index.tsx @@ -11,6 +11,7 @@ import { getCurrentAreaId } from "../../../../../../../redux/selectors"; function Hydro() { const { study } = useOutletContext<{ study: StudyMetadata }>(); const areaId = useAppSelector(getCurrentAreaId); + const studyVersion = parseInt(study.version, 10); const tabList = useMemo(() => { const basePath = `/studies/${study?.id}/explore/modelization/area/${encodeURI( @@ -30,8 +31,9 @@ function Hydro() { { label: "Water values", path: `${basePath}/watervalues` }, { label: "Hydro Storage", path: `${basePath}/hydrostorage` }, { label: "Run of river", path: `${basePath}/ror` }, - ]; - }, [areaId, study?.id]); + studyVersion >= 860 && { label: "Min Gen", path: `${basePath}/mingen` }, + ].filter(Boolean); + }, [areaId, study?.id, studyVersion]); //////////////////////////////////////////////////////////////// // JSX diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/utils.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/utils.ts index 8fc143d280..7b4878aa73 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/utils.ts @@ -15,6 +15,7 @@ export enum HydroMatrixType { WaterValues, HydroStorage, RunOfRiver, + MinGen, InflowPattern, OverallMonthlyHydro, Allocation, @@ -99,6 +100,10 @@ export const HYDRO_ROUTES: HydroRoute[] = [ path: "ror", type: HydroMatrixType.RunOfRiver, }, + { + path: "mingen", + type: HydroMatrixType.MinGen, + }, ]; export const MATRICES: Matrices = { @@ -144,6 +149,11 @@ export const MATRICES: Matrices = { url: "input/hydro/series/{areaId}/ror", stats: MatrixStats.STATS, }, + [HydroMatrixType.MinGen]: { + title: "Min Gen", + url: "input/hydro/series/{areaId}/mingen", + stats: MatrixStats.STATS, + }, [HydroMatrixType.InflowPattern]: { title: "Inflow Pattern", url: "input/hydro/common/capacity/inflowPattern_{areaId}", @@ -200,7 +210,8 @@ export const MATRICES: Matrices = { /** * Generates an array of column names from 0 to 100, optionally with a suffix. - * @param columnSuffix The suffix to append to the column names. + * + * @param columnSuffix - The suffix to append to the column names. * @returns An array of strings representing column names from 0 to 100. */ function generateColumns(columnSuffix = ""): string[] { diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Properties/Fields.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Properties/Fields.tsx index 2ec3ec8df9..01a98538be 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Properties/Fields.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Properties/Fields.tsx @@ -3,7 +3,6 @@ import { useOutletContext } from "react-router"; import { useMemo } from "react"; import SelectFE from "../../../../../../common/fieldEditors/SelectFE"; import Fieldset from "../../../../../../common/Fieldset"; -import ColorPickerFE from "../../../../../../common/fieldEditors/ColorPickerFE"; import SwitchFE from "../../../../../../common/fieldEditors/SwitchFE"; import NumberFE from "../../../../../../common/fieldEditors/NumberFE"; import { useFormContextPlus } from "../../../../../../common/Form"; @@ -27,23 +26,6 @@ function Fields() { return ( <> -
- - - -
; open: boolean; onClose: VoidFunction; + existingConstraints: Array; + reloadConstraintsList: VoidFunction; } -function AddDialog({ studyId, existingConstraints, open, onClose }: Props) { - const [t] = useTranslation(); +// TODO rename AddConstraintDialog +function AddDialog({ + open, + onClose, + existingConstraints, + reloadConstraintsList, +}: Props) { + const { study } = useOutletContext<{ study: StudyMetadata }>(); const { enqueueSnackbar } = useSnackbar(); + const dispatch = useAppDispatch(); + const [t] = useTranslation(); + const studyVersion = Number(study.version); const defaultValues = { name: "", + group: studyVersion >= 870 ? "default" : "", enabled: true, - time_step: TimeStep.HOURLY, + timeStep: TimeStep.HOURLY, operator: BindingConstraintOperator.LESS, comments: "", - coeffs: {}, }; const operatorOptions = useMemo( () => - ["less", "equal", "greater", "both"].map((item) => ({ - label: t(`study.modelization.bindingConst.operator.${item}`), - value: item, + OPERATORS.map((operator) => ({ + label: t(`study.modelization.bindingConst.operator.${operator}`), + value: operator, })), [t], ); - const typeOptions = useMemo( + const timeStepOptions = useMemo( () => - ["hourly", "daily", "weekly"].map((item) => ({ - label: t(`global.time.${item}`), - value: item, + TIME_STEPS.map((timeStep) => ({ + label: t(`global.time.${timeStep}`), + value: timeStep, })), [t], ); @@ -58,13 +74,36 @@ function AddDialog({ studyId, existingConstraints, open, onClose }: Props) { // Event Handlers //////////////////////////////////////////////////////////////// - const handleSubmit = async ( - data: SubmitHandlerPlus, - ) => { - return createBindingConstraint(studyId, data.values); + const handleSubmit = ({ + values, + }: SubmitHandlerPlus) => { + return createBindingConstraint(study.id, values); }; - const handleSubmitSuccessful = () => { + const handleSubmitSuccessful = ( + data: SubmitHandlerPlus, + createdConstraint: BindingConstraint, + ) => { + /** + * !WARNING: Current Implementation Issues & Future Directions + * + * Issues Identified: + * 1. State vs. Router: Utilizes global state for navigation-related concerns better suited for URL routing, reducing shareability and persistence. + * 2. Full List Reload: Inefficiently reloads the entire list after adding an item, leading to unnecessary network use and performance hits. + * 3. Global State Overuse: Over-relies on global state for operations that could be localized, complicating the application unnecessarily. + * + * Future Solutions: + * - React Router Integration: Leverage URL parameters for selecting and displaying binding constraints, improving UX and state persistence. + * - React Query for State Management: Utilize React Query for data fetching and state management. This introduces benefits like: + * - Automatic Revalidation: Only fetches data when needed, reducing unnecessary network requests. + * - Optimistic Updates: Immediately reflect changes in the UI while the backend processes the request, enhancing perceived performance. + * - Cache Management: Efficiently manage and invalidate cache, ensuring data consistency without manual reloads. + * - Efficient State Updates: Post-creation, append the new item to the existing list or use React Query's mutation to update the list optimally. + * + * Adopting these strategies will significantly enhance efficiency, maintainability, and UX, addressing current architectural weaknesses. + */ + reloadConstraintsList(); + dispatch(setCurrentBindingConst(createdConstraint.id)); enqueueSnackbar(t("study.success.addBindingConst"), { variant: "success", }); @@ -77,7 +116,7 @@ function AddDialog({ studyId, existingConstraints, open, onClose }: Props) { return ( - validateString(v, { existingValues: existingConstraints }), + validateString(v, { + existingValues: existingConstraints, + specialChars: "@&_-()", + }), }} /> + {studyVersion >= 870 && ( + + validateString(v, { + max: 20, + specialChars: "-", + }), + }} + /> + )} void; - list: BindingConstFields[]; - studyId: StudyMetadata["id"]; - currentBindingConst?: string; + currentConstraint?: string; + reloadConstraintsList: VoidFunction; } -function BindingConstPropsView(props: Props) { - const { onClick, currentBindingConst, studyId, list } = props; - const [bindingConstNameFilter, setBindingConstNameFilter] = - useState(); +// TODO rename ConstraintsList +function BindingConstPropsView({ + list, + onClick, + currentConstraint, + reloadConstraintsList, +}: Props) { + const [searchedConstraint, setSearchedConstraint] = useState(""); const [addBindingConst, setAddBindingConst] = useState(false); - const [filteredBindingConst, setFilteredBindingConst] = useState< - BindingConstFields[] - >(list || []); + const [filteredConstraints, setFilteredConstraints] = useState(list); useEffect(() => { - const filter = (): BindingConstFields[] => { - if (list) { - return list.filter( - (s) => - !bindingConstNameFilter || - s.name.search(new RegExp(bindingConstNameFilter, "i")) !== -1, - ); - } - return []; - }; - setFilteredBindingConst(filter()); - }, [list, bindingConstNameFilter]); + if (!list) { + setFilteredConstraints([]); + return; + } + + if (!searchedConstraint) { + setFilteredConstraints(list); + return; + } + + const pattern = new RegExp(searchedConstraint, "i"); + const filtered = list.filter((s) => pattern.test(s.name)); + + setFilteredConstraints(filtered); + }, [list, searchedConstraint]); const existingConstraints = useMemo( - () => list.map(({ name }) => name.toLowerCase()), + () => list.map(({ name }) => name), [list], ); @@ -49,23 +53,23 @@ function BindingConstPropsView(props: Props) { ({ - label: item.name, - name: item.id, + list={filteredConstraints.map((constraint) => ({ + label: constraint.name, + name: constraint.id, }))} - currentElement={currentBindingConst} + currentElement={currentConstraint} setSelectedItem={(elm) => onClick(elm.name)} /> } secondaryContent={
} onAdd={() => setAddBindingConst(true)} - onSearchFilterChange={(e) => setBindingConstNameFilter(e as string)} + onSearchFilterChange={(e) => setSearchedConstraint(e)} /> {addBindingConst && ( setAddBindingConst(false)} /> )} @@ -73,8 +77,4 @@ function BindingConstPropsView(props: Props) { ); } -BindingConstPropsView.defaultProps = { - currentBindingConst: undefined, -}; - export default BindingConstPropsView; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/AddConstraintTermForm/OptionsList.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/AddConstraintTermForm/OptionsList.tsx index 8c8bf80ad0..c7c1c5f862 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/AddConstraintTermForm/OptionsList.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/AddConstraintTermForm/OptionsList.tsx @@ -1,117 +1,89 @@ -import { useEffect, useMemo, useState } from "react"; -import { - UseFormSetValue, - UseFormUnregister, - UseFormWatch, -} from "react-hook-form"; +import { useEffect } from "react"; import { useTranslation } from "react-i18next"; -import { AllClustersAndLinks } from "../../../../../../../../../common/types"; +import { useFormContext } from "react-hook-form"; import SelectFE from "../../../../../../../../common/fieldEditors/SelectFE"; -import { ControlPlus } from "../../../../../../../../common/Form/types"; -import { - BindingConstFields, - ConstraintType, - dataToId, - isTermExist, -} from "../../utils"; +import { AllClustersAndLinks } from "../../../../../../../../../common/types"; +import { ConstraintTerm, isTermExist, generateTermId } from "../../utils"; interface Props { list: AllClustersAndLinks; isLink: boolean; - control: ControlPlus; - watch: UseFormWatch; - constraintsTerm: BindingConstFields["constraints"]; - setValue: UseFormSetValue; - unregister: UseFormUnregister; + constraintTerms: ConstraintTerm[]; } -export default function OptionsList(props: Props) { - const { - list, - isLink, - control, - constraintsTerm, - watch, - setValue, - unregister, - } = props; +export default function OptionsList({ list, isLink, constraintTerms }: Props) { const [t] = useTranslation(); - const name1 = isLink ? "area1" : "area"; - const name2 = isLink ? "area2" : "cluster"; - const linksOrClusters = isLink ? list.links : list.clusters; - const options1 = useMemo(() => { - return linksOrClusters.map((elm) => ({ - label: elm.element.name, - value: elm.element.id, - })); - }, [linksOrClusters]); - const [options2, setOptions2] = useState< - Array<{ label: string; value: string }> - >([]); + const { control, setValue, watch, getValues } = + useFormContext(); - const watchSelect1 = watch(`data.${name1}`); + // Determines the correct set of options based on whether the term is a link or a cluster. + const options = isLink ? list.links : list.clusters; - useEffect(() => { - unregister( - isLink ? ["data.area", "data.cluster"] : ["data.area1", "data.area2"], - ); - setValue(`data.${name1}`, ""); - setValue(`data.${name2}`, ""); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isLink]); + const areaOptions = options.map(({ element }) => ({ + label: element.name, + value: element.id, + })); + + // Watching changes to the primary selection to update secondary options accordingly. + const primarySelection = watch(isLink ? "data.area1" : "data.area"); useEffect(() => { - const index = linksOrClusters.findIndex( - (elm) => elm.element.id === watchSelect1, + setValue(isLink ? "data.area2" : "data.cluster", ""); + }, [primarySelection, isLink, setValue]); + + const getAreaOrClusterOptions = () => { + const selectedArea = getValues(isLink ? "data.area1" : "data.area"); + + const foundOption = options.find( + (option) => option.element.id === selectedArea, ); - if (index >= 0) { - setOptions2( - linksOrClusters[index].item_list - .filter( - (elm) => - !isTermExist( - constraintsTerm, - dataToId( - isLink - ? { - area1: watchSelect1, - area2: elm.id, - } - : { area: watchSelect1, cluster: elm.id }, - ), - ), - ) - .map((elm) => ({ - label: elm.name, - value: elm.id, - })), - ); + + if (!foundOption) { + return []; } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [watchSelect1]); + + return foundOption.item_list + .filter( + ({ id }) => + !isTermExist( + constraintTerms, + generateTermId( + isLink + ? { area1: selectedArea, area2: id } + : { area: selectedArea, cluster: id }, + ), + ), + ) + .map(({ name, id }) => ({ + label: name, + value: id, + })); + }; + + const areaOrClusterOptions = getAreaOrClusterOptions(); + + //////////////////////////////////////////////////////////////// + // JSX + //////////////////////////////////////////////////////////////// return ( <> ); diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/AddConstraintTermForm/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/AddConstraintTermForm/index.tsx index e833cbe810..4290b3e599 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/AddConstraintTermForm/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/AddConstraintTermForm/index.tsx @@ -6,98 +6,105 @@ import { AllClustersAndLinks } from "../../../../../../../../../common/types"; import OptionsList from "./OptionsList"; import NumberFE from "../../../../../../../../common/fieldEditors/NumberFE"; import { useFormContextPlus } from "../../../../../../../../common/Form"; -import { ConstraintItemRoot } from "../../ConstraintTerm/style"; -import { BindingConstFields, ConstraintType } from "../../utils"; +import { type ConstraintTerm } from "../../utils"; import ConstraintElement from "../../constraintviews/ConstraintElement"; import OffsetInput from "../../constraintviews/OffsetInput"; interface Props { options: AllClustersAndLinks; - constraintsTerm: BindingConstFields["constraints"]; + constraintTerms: ConstraintTerm[]; } -export default function AddConstraintTermForm(props: Props) { - const { options, constraintsTerm } = props; - const { control, watch, unregister, setValue } = - useFormContextPlus(); +export default function AddConstraintTermForm({ + options, + constraintTerms, +}: Props) { + const { control, setValue } = useFormContextPlus(); const [t] = useTranslation(); const [isLink, setIsLink] = useState(true); const [isOffset, setIsOffset] = useState(false); + //////////////////////////////////////////////////////////////// + // Event handlers + //////////////////////////////////////////////////////////////// + + const handleOffsetRemove = () => { + setValue("offset", undefined); + setIsOffset(false); + }; + + //////////////////////////////////////////////////////////////// + // JSX + //////////////////////////////////////////////////////////////// + return ( - - setIsLink((value) => !value)} - left={ - - } - right={ - - - - } - /> - {isOffset ? ( - <> - x - t} - right={ - setIsOffset(false)}> - - - } + setIsLink((value) => !value)} + left={ + + } + right={ + + - - ) : ( - - )} - + + } + /> + {isOffset ? ( + <> + x + t} + right={ + + + + } + /> + + ) : ( + + )} ); } diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/index.tsx index 5197645e5b..f6a5d6ed59 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/AddConstraintTermDialog/index.tsx @@ -8,54 +8,79 @@ import FormDialog, { import { SubmitHandlerPlus } from "../../../../../../../common/Form/types"; import useEnqueueErrorSnackbar from "../../../../../../../../hooks/useEnqueueErrorSnackbar"; import { - BindingConstFields, - ConstraintType, - dataToId, - isDataLink, - isOptionExist, - isTermExist, + isLinkTerm, + type BindingConstraint, + type ConstraintTerm, } from "../utils"; import AddConstraintTermForm from "./AddConstraintTermForm"; -import { addConstraintTerm } from "../../../../../../../../services/api/studydata"; -import { - AllClustersAndLinks, - ClusterElement, - LinkCreationInfoDTO, -} from "../../../../../../../../common/types"; +import { createConstraintTerm } from "../../../../../../../../services/api/studydata"; +import { AllClustersAndLinks } from "../../../../../../../../common/types"; import useStudySynthesis from "../../../../../../../../redux/hooks/useStudySynthesis"; import { getLinksAndClusters } from "../../../../../../../../redux/selectors"; +import { BaseSyntheticEvent } from "react"; +import UsePromiseCond from "../../../../../../../common/utils/UsePromiseCond"; interface Props extends Omit { studyId: string; - bindingConstraint: string; - append: UseFieldArrayAppend; - constraintsTerm: BindingConstFields["constraints"]; + constraintId: string; + append: UseFieldArrayAppend; + constraintTerms: ConstraintTerm[]; options: AllClustersAndLinks; } -function AddConstraintTermDialog(props: Props) { +const defaultValues = { + id: "", + weight: 0, + offset: undefined, + data: { + area1: "", + area2: "", + }, +}; + +/** + * @deprecated This form and all its children are deprecated due to the original design mixing different + * types of terms (links and clusters) in a single form state. This approach has proven to be problematic, + * leading to a non-separate and imprecise form state management. Future development should focus on + * separating these concerns into distinct components or forms to ensure cleaner, more maintainable code. + * + * The current workaround involves conditionally constructing the `newTerm` object based on the term type, + * which is not ideal and should be avoided in future designs. + * + * Potential Future Optimizations: + * - Separate link and cluster term forms into distinct components to simplify state management and + * improve type safety. + * - Implement more granular type checks or leverage TypeScript discriminated unions more effectively + * to avoid runtime type assertions and ensure compile-time type safety. + * - Consider redesigning the form state structure to more clearly differentiate between link and cluster + * terms from the outset, possibly using separate state variables or contexts. + * + * Note: This component is not expected to evolve further in its current form. Any necessary bug fixes or + * minor improvements should be approached with caution, keeping in mind the planned obsolescence. + * + * @param props - The props passed to the component. + * @param props.studyId - Identifier for the study to which the constraint term is being added. + * @param props.constraintId - Identifier for the specific constraint to which the term is added. + * @param props.options - Object containing potential options for populating form selects. + * @param props.constraintTerms - Array of existing constraint terms. + * @param props.append - Function to append the new term to the array of existing terms. + * + *@returns A React component that renders the form dialog for adding a constraint term. + */ +function AddConstraintTermDialog({ + studyId, + constraintId, + options, + constraintTerms, + append, + ...dialogProps +}: Props) { const [t] = useTranslation(); - const enqueueErrorSnackbar = useEnqueueErrorSnackbar(); - const { enqueueSnackbar } = useSnackbar(); - const { - studyId, - bindingConstraint, - options, - constraintsTerm, - append, - ...dialogProps - } = props; const { onCancel } = dialogProps; - const defaultValues: ConstraintType = { - id: "", - weight: 0, - offset: 0, - data: { - area1: "", - area2: "", - }, - }; - const { data: optionsItems } = useStudySynthesis({ + const { enqueueSnackbar } = useSnackbar(); + const enqueueErrorSnackbar = useEnqueueErrorSnackbar(); + + const linksAndClusters = useStudySynthesis({ studyId, selector: (state) => getLinksAndClusters(state, studyId), }); @@ -64,67 +89,48 @@ function AddConstraintTermDialog(props: Props) { // Event Handlers //////////////////////////////////////////////////////////////// - const handleSubmit = async (values: SubmitHandlerPlus) => { + /** + * @deprecated Due to the challenges and limitations associated with dynamically determining term types + * and constructing term data based on runtime checks, this method is deprecated. Future implementations + * should consider using separate and explicit handling for different term types to enhance type safety, + * reduce complexity, and improve code maintainability. + * + * Potential future optimizations include adopting separate forms for link and cluster terms, leveraging + * TypeScript's type system more effectively, and implementing robust form validation. + * + * @param root0 - The first parameter object containing all form values. + * @param root0.values - The structured data of the form, including details about the term being submitted. + * It includes both link and cluster term fields due to the unified form design. + * @param _event - The event object for the form submission. May not be + * used explicitly in the function but is included to match the expected handler signature. + * + * @returns A promise that resolves when the term has been successfully submitted + * and processed or rejects in case of an error. + */ + const handleSubmit = async ( + { values }: SubmitHandlerPlus, + _event?: BaseSyntheticEvent, + ) => { try { - const tmpValues = values.dirtyValues as ConstraintType; - const isLink = isDataLink(tmpValues.data); - if (tmpValues.weight === undefined) { - tmpValues.weight = 0.0; - } - let data: LinkCreationInfoDTO | ClusterElement; - // Verify if this link/cluster combination is allowed - if (isLink) { - data = tmpValues.data as LinkCreationInfoDTO; - if (!isOptionExist(options.links, data.area1, data.area2)) { - enqueueSnackbar( - t("study.error.missingData", { - 0: t("study.area1"), - 1: t("study.area2"), - }), - { variant: "error" }, - ); - onCancel(); - return; - } - } else { - data = tmpValues.data as ClusterElement; - if (!isOptionExist(options.clusters, data.area, data.cluster)) { - enqueueSnackbar( - t("study.error.missingData", { - 0: t("study.area"), - 1: t("study.cluster"), - }), - { variant: "error" }, - ); - onCancel(); - return; - } - } + const newTerm = { + ...values, + data: isLinkTerm(values.data) + ? { area1: values.data.area1, area2: values.data.area2 } + : { area: values.data.area, cluster: values.data.cluster }, + }; - // Verify if this term already exist in current term list - const termId = dataToId(data); - if (isTermExist(constraintsTerm, termId)) { - enqueueSnackbar(t("study.error.termAlreadyExist"), { - variant: "error", - }); - onCancel(); - return; - } + await createConstraintTerm(studyId, constraintId, newTerm); - // Send - await addConstraintTerm( - studyId, - bindingConstraint, - values.dirtyValues as ConstraintType, - ); + append(newTerm); - // Add to current UX - append(tmpValues as ConstraintType); - enqueueSnackbar(t("study.success.addConstraintTerm"), { + enqueueSnackbar(t("study.success.createConstraintTerm"), { variant: "success", }); } catch (e) { - enqueueErrorSnackbar(t("study.error.addConstraintTerm"), e as AxiosError); + enqueueErrorSnackbar( + t("study.error.createConstraintTerm"), + e as AxiosError, + ); } finally { onCancel(); } @@ -136,17 +142,21 @@ function AddConstraintTermDialog(props: Props) { return ( - {optionsItems && ( - - )} + ( + + )} + /> ); } diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/BindingConstForm.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/BindingConstForm.tsx index a6c574497b..a28a2644fc 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/BindingConstForm.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/BindingConstForm.tsx @@ -1,153 +1,85 @@ import { AxiosError } from "axios"; -import { useCallback, useMemo, useState } from "react"; +import { useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; -import { Box, Button, Tab, Typography } from "@mui/material"; -import { useFieldArray } from "react-hook-form"; +import { Box, Button } from "@mui/material"; +import AddCircleOutlineRoundedIcon from "@mui/icons-material/AddCircleOutlineRounded"; import DeleteIcon from "@mui/icons-material/Delete"; +import { useFieldArray } from "react-hook-form"; import { useSnackbar } from "notistack"; -import { useNavigate } from "react-router-dom"; import useEnqueueErrorSnackbar from "../../../../../../../hooks/useEnqueueErrorSnackbar"; import { - ACTIVE_WINDOWS_DOC_PATH, - BindingConstFields, - ConstraintType, - dataToId, + type ConstraintTerm, + generateTermId, + BindingConstraint, } from "./utils"; import { AllClustersAndLinks, - MatrixStats, StudyMetadata, } from "../../../../../../../common/types"; -import { IFormGenerator } from "../../../../../../common/FormGenerator"; -import AutoSubmitGeneratorForm from "../../../../../../common/FormGenerator/AutoSubmitGenerator"; -import ConstraintItem, { ConstraintWithNullableOffset } from "./ConstraintTerm"; +import ConstraintTermItem from "./ConstraintTerm"; import { useFormContextPlus } from "../../../../../../common/Form"; import { deleteConstraintTerm, - updateBindingConstraint, updateConstraintTerm, } from "../../../../../../../services/api/studydata"; import TextSeparator from "../../../../../../common/TextSeparator"; -import { - ConstraintHeader, - ConstraintList, - ConstraintTerm, - MatrixContainer, - StyledTab, -} from "./style"; import AddConstraintTermDialog from "./AddConstraintTermDialog"; -import MatrixInput from "../../../../../../common/MatrixInput"; import ConfirmationDialog from "../../../../../../common/dialogs/ConfirmationDialog"; import useDebounce from "../../../../../../../hooks/useDebounce"; -import { appendCommands } from "../../../../../../../services/api/variant"; -import { CommandEnum } from "../../../../Commands/Edition/commandTypes"; -import useAppDispatch from "../../../../../../../redux/hooks/useAppDispatch"; -import { setCurrentBindingConst } from "../../../../../../../redux/ducks/studySyntheses"; -import OutputFilters from "../../../common/OutputFilters"; -import DocLink from "../../../../../../common/DocLink"; - -const DEBOUNCE_DELAY = 200; +import Fieldset from "../../../../../../common/Fieldset"; interface Props { study: StudyMetadata; - bindingConst: string; + constraintId: string; options: AllClustersAndLinks; } -export default function BindingConstForm(props: Props) { - const { study, options, bindingConst } = props; - const studyId = study.id; +// TODO rename ConstraintTermsFields +function BindingConstForm({ study, options, constraintId }: Props) { + const [t] = useTranslation(); const { enqueueSnackbar } = useSnackbar(); const enqueueErrorSnackbar = useEnqueueErrorSnackbar(); - const [t] = useTranslation(); - const dispatch = useAppDispatch(); - const navigate = useNavigate(); - const { control } = useFormContextPlus(); + const [termToDelete, setTermToDelete] = useState(); + const [openConstraintTermDialog, setOpenConstraintTermDialog] = + useState(false); + + const { control } = useFormContextPlus(); + const { fields, update, append, remove } = useFieldArray({ control, - name: "constraints", + name: "terms", }); - const constraintsTerm = useMemo( - () => fields.map((elm) => ({ ...elm, id: dataToId(elm.data) })), + const constraintTerms = useMemo( + () => fields.map((term) => ({ ...term, id: generateTermId(term.data) })), [fields], ); - const pathPrefix = `input/bindingconstraints/bindingconstraints`; - - const optionOperator = useMemo( - () => - ["less", "equal", "greater", "both"].map((item) => ({ - label: t(`study.modelization.bindingConst.operator.${item}`), - value: item.toLowerCase(), - })), - [t], - ); - - const typeOptions = useMemo( - () => - ["hourly", "daily", "weekly"].map((item) => ({ - label: t(`global.time.${item}`), - value: item, - })), - [t], - ); - - const [addConstraintTermDialog, setAddConstraintTermDialog] = useState(false); - const [deleteConstraint, setDeleteConstraint] = useState(false); - const [termToDelete, setTermToDelete] = useState(); - const [tabValue, setTabValue] = useState(0); - //////////////////////////////////////////////////////////////// // Event Handlers //////////////////////////////////////////////////////////////// - const saveValue = useCallback( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - async (name: string, data: any) => { - try { - await updateBindingConstraint(studyId, bindingConst, { - key: name, - value: data, - }); - } catch (error) { - enqueueErrorSnackbar(t("study.error.updateUI"), error as AxiosError); - } - }, - [bindingConst, enqueueErrorSnackbar, studyId, t], - ); - - const saveValueFormGenerator = useCallback( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - async (name: string, path: string, defaultValues: any, data: any) => - saveValue(name, data), - [saveValue], - ); - - const saveContraintValue = useDebounce( + const handleUpdateTerm = useDebounce( async ( index: number, - prevConst: ConstraintType, - constraint: ConstraintWithNullableOffset, + prevTerm: ConstraintTerm, + newTerm: ConstraintTerm, ) => { try { - const tmpConst = prevConst; - if (constraint.weight !== undefined) { - tmpConst.weight = constraint.weight; - } - if (constraint.data) { - tmpConst.data = constraint.data; - } - tmpConst.id = dataToId(tmpConst.data); - if (constraint.offset !== undefined) { - tmpConst.offset = - constraint.offset !== null ? constraint.offset : undefined; - } - await updateConstraintTerm(study.id, bindingConst, { - ...constraint, - offset: tmpConst.offset, + const updatedTerm = { + ...prevTerm, + weight: newTerm.weight || prevTerm.weight, + data: newTerm.data || prevTerm.data, + offset: newTerm.offset || undefined, + }; + + await updateConstraintTerm(study.id, constraintId, updatedTerm); + + update(index, updatedTerm); + + enqueueSnackbar(t("global.update.success"), { + variant: "success", }); - update(index, tmpConst); } catch (error) { enqueueErrorSnackbar( t("study.error.updateConstraintTerm"), @@ -155,274 +87,93 @@ export default function BindingConstForm(props: Props) { ); } }, - DEBOUNCE_DELAY, + 500, ); - const deleteTerm = useCallback( - async (index: number) => { - try { - const constraintId = dataToId(constraintsTerm[index].data); - await deleteConstraintTerm(study.id, bindingConst, constraintId); - remove(index); - } catch (error) { - enqueueErrorSnackbar( - t("study.error.deleteConstraintTerm"), - error as AxiosError, - ); - } finally { - setTermToDelete(undefined); - } - }, - [bindingConst, enqueueErrorSnackbar, constraintsTerm, remove, study.id, t], - ); - - const handleConstraintDeletion = useCallback(async () => { + const handleDeleteTerm = async (termToDelete: number) => { try { - await appendCommands(study.id, [ - { - action: CommandEnum.REMOVE_BINDING_CONSTRAINT, - args: { - id: bindingConst, - }, - }, - ]); - enqueueSnackbar(t("study.success.deleteConstraint"), { - variant: "success", - }); - dispatch(setCurrentBindingConst("")); - navigate(`/studies/${study.id}/explore/modelization/bindingcontraint`); - } catch (e) { - enqueueErrorSnackbar(t("study.error.deleteConstraint"), e as AxiosError); + const termId = generateTermId(constraintTerms[termToDelete].data); + await deleteConstraintTerm(study.id, constraintId, termId); + remove(termToDelete); + } catch (error) { + enqueueErrorSnackbar( + t("study.error.deleteConstraintTerm"), + error as AxiosError, + ); } finally { - setDeleteConstraint(false); + setTermToDelete(undefined); } - }, [ - bindingConst, - dispatch, - enqueueErrorSnackbar, - enqueueSnackbar, - navigate, - study.id, - t, - ]); - - const handleTabChange = (event: React.SyntheticEvent, newValue: number) => { - setTabValue(newValue); }; //////////////////////////////////////////////////////////////// // JSX //////////////////////////////////////////////////////////////// - const jsonGenerator: IFormGenerator = useMemo( - () => [ - { - legend: ( + return ( + <> +
+ - } + onClick={() => setOpenConstraintTermDialog(true)} > - {t("global.general")} - - - - - - + {t("study.modelization.bindingConst.createConstraintTerm")} + - ), - fields: [ - { - type: "text", - name: "name", - path: `${pathPrefix}/name`, - label: t("global.name"), - disabled: true, - required: t("form.field.required") as string, - }, - { - type: "text", - name: "comments", - path: `${pathPrefix}/comments`, - label: t("study.modelization.bindingConst.comments"), - }, - { - type: "select", - name: "time_step", - path: `${pathPrefix}/type`, - label: t("study.modelization.bindingConst.type"), - options: typeOptions, - }, - { - type: "select", - name: "operator", - path: `${pathPrefix}/operator`, - label: t("study.modelization.bindingConst.operator"), - options: optionOperator, - }, - { - type: "switch", - name: "enabled", - path: `${pathPrefix}/enabled`, - label: t("study.modelization.bindingConst.enabled"), - }, - ], - }, - ], - [optionOperator, pathPrefix, t, typeOptions], - ); - - return ( - <> - - {Number(study.version) >= 840 && ( - - )} - - - - - - - {tabValue === 0 ? ( - <> - - - - - {constraintsTerm.map( - (constraint: ConstraintType, index: number) => { - return index > 0 ? ( - - - - saveContraintValue(index, constraint, value) - } - constraint={constraint} - deleteTerm={() => setTermToDelete(index)} - constraintsTerm={constraintsTerm} - /> - - ) : ( - - saveContraintValue(index, constraint, value) - } - constraint={constraint} - deleteTerm={() => setTermToDelete(index)} - constraintsTerm={constraintsTerm} - /> - ); - }, - )} - - {addConstraintTermDialog && ( - setAddConstraintTermDialog(false)} - append={append} - constraintsTerm={constraintsTerm} - options={options} - /> - )} - {termToDelete !== undefined && ( - setTermToDelete(undefined)} - onConfirm={() => deleteTerm(termToDelete)} - alert="warning" - open - > - {t( - "study.modelization.bindingConst.question.deleteConstraintTerm", - )} - + {constraintTerms.map((term: ConstraintTerm, index: number) => ( + + {index > 0 && ( + )} - {deleteConstraint && ( - setDeleteConstraint(false)} - onConfirm={() => handleConstraintDeletion()} - alert="warning" - open - > - {t( - "study.modelization.bindingConst.question.deleteBindingConstraint", - )} - - )} - - ) : ( - - ", "="]} - computStats={MatrixStats.NOCOL} + handleUpdateTerm(index, term, newTerm)} + term={term} + deleteTerm={() => setTermToDelete(index)} + constraintTerms={constraintTerms} /> - - )} + + ))} - +
+ + {openConstraintTermDialog && ( + setOpenConstraintTermDialog(false)} + append={append} + constraintTerms={constraintTerms} + options={options} + /> + )} + + {termToDelete !== undefined && ( + setTermToDelete(undefined)} + onConfirm={() => handleDeleteTerm(termToDelete)} + alert="warning" + open + > + {t("study.modelization.bindingConst.question.deleteConstraintTerm")} + + )} ); } + +export default BindingConstForm; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintFields.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintFields.tsx new file mode 100644 index 0000000000..3405540a6e --- /dev/null +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintFields.tsx @@ -0,0 +1,175 @@ +import { + BindingConstraint, + OPERATORS, + OUTPUT_FILTERS, + TIME_STEPS, +} from "./utils"; + +import Fieldset from "../../../../../../common/Fieldset"; +import SelectFE from "../../../../../../common/fieldEditors/SelectFE"; +import StringFE from "../../../../../../common/fieldEditors/StringFE"; +import { StudyMetadata } from "../../../../../../../common/types"; +import SwitchFE from "../../../../../../common/fieldEditors/SwitchFE"; +import { useFormContextPlus } from "../../../../../../common/Form"; +import { useMemo, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { validateString } from "../../../../../../../utils/validationUtils"; +import Matrix from "./Matrix"; +import { Box, Button } from "@mui/material"; +import { Dataset } from "@mui/icons-material"; + +interface Props { + study: StudyMetadata; + constraintId: string; +} + +function Fields({ study, constraintId }: Props) { + const { t } = useTranslation(); + const { control, getValues } = useFormContextPlus(); + const [matrixDialogOpen, setMatrixDialogOpen] = useState(false); + const currentOperator = getValues("operator"); + + const outputFilterOptions = useMemo( + () => + OUTPUT_FILTERS.map((filter) => ({ + label: t(`global.time.${filter}`), + value: filter, + })), + [t], + ); + + const operatorOptions = useMemo( + () => + OPERATORS.map((operator) => ({ + label: t(`study.modelization.bindingConst.operator.${operator}`), + value: operator, + })), + [t], + ); + + const timeStepOptions = useMemo( + () => + TIME_STEPS.map((timeStep) => ({ + label: t(`global.time.${timeStep}`), + value: timeStep, + })), + [t], + ); + + //////////////////////////////////////////////////////////////// + // JSX + //////////////////////////////////////////////////////////////// + + return ( + <> +
+ + validateString(v) }} + sx={{ m: 0, minWidth: 280 }} // TODO: Remove margin reset when updating MUI Theme + /> + {Number(study.version) >= 870 && ( + + validateString(v, { + max: 20, + specialChars: "-", + }), + }} + sx={{ m: 0, minWidth: 280 }} // TODO: Remove margin reset when updating MUI Theme + /> + )} + + + {Number(study.version) >= 830 && ( + + + + + + )} +
+ + + + + {matrixDialogOpen && ( + setMatrixDialogOpen(false)} + /> + )} + + ); +} + +export default Fields; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintTerm/OptionsList.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintTerm/OptionsList.tsx index 3fbfae70f3..ee627fa126 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintTerm/OptionsList.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintTerm/OptionsList.tsx @@ -1,156 +1,140 @@ -import { useCallback, useMemo } from "react"; +import { useMemo } from "react"; import { useTranslation } from "react-i18next"; import { AllClustersAndLinks } from "../../../../../../../../common/types"; import SelectSingle from "../../../../../../../common/SelectSingle"; -import { ConstraintType, dataToId, isTermExist } from "../utils"; +import { ConstraintTerm, generateTermId, isTermExist } from "../utils"; +interface Option { + id: string; + name: string; +} interface Props { list: AllClustersAndLinks; isLink: boolean; - constraint: ConstraintType; - constraintsTerm: ConstraintType[]; - saveValue: (constraint: Partial) => void; - value1: string; - value2: string; - setValue1: (value: string) => void; - setValue2: (value: string) => void; + term: ConstraintTerm; + constraintTerms: ConstraintTerm[]; + saveValue: (term: ConstraintTerm) => void; + selectedArea: string; + selectedClusterOrArea: string; + setSelectedArea: (value: string) => void; + setSelectedClusterOrArea: (value: string) => void; } -export default function OptionsList(props: Props) { - const { - list, - isLink, - constraint, - value1, - value2, - constraintsTerm, - saveValue, - setValue1, - setValue2, - } = props; +export default function OptionsList({ + list, + isLink, + term, + constraintTerms, + saveValue, + selectedArea, + selectedClusterOrArea, + setSelectedArea, + setSelectedClusterOrArea, +}: Props) { const [t] = useTranslation(); - const name1 = isLink ? "area1" : "area"; - const name2 = isLink ? "area2" : "cluster"; - const options = isLink ? list.links : list.clusters; - const options1 = useMemo(() => { - return options.map((elm) => ({ - name: elm.element.name, - id: elm.element.id, - })); - }, [options]); - const options2 = useMemo(() => { - const index = options.findIndex((elm) => elm.element.id === value1); - if (index < 0) { + const areaOptions = useMemo( + () => + list.links.map(({ element }) => ({ + name: element.name, + id: element.id, + })), + [list.links], + ); + + const clusterOrAreaOptions = useMemo(() => { + if (!selectedArea) { return []; } - const tmp = options[index].item_list - .filter( - (elm) => - elm.id === value2 || - !isTermExist( - constraintsTerm, - dataToId( - isLink - ? { - area1: value1, - area2: elm.id, - } - : { area: value1, cluster: elm.id }, - ), - ), - ) - .map((elm) => ({ - name: elm.name, - id: elm.id.toLowerCase(), - })); - return tmp; - }, [constraintsTerm, isLink, options, value1, value2]); + // Determine the type of options to use based on whether it is a link or cluster + const relatedOptions = isLink ? list.links : list.clusters; + + // Attempt to find the option that matches the selected area + const foundOption = relatedOptions.find( + ({ element }) => element.id === selectedArea, + ); + + if (!foundOption) { + return []; + } - const getFirstValue2 = useCallback( - (value: string): string => { - const index = options1.findIndex((elm) => elm.id === value); - if (index >= 0) { - return options[index].item_list[0].id; + return foundOption.item_list.reduce((acc, { id, name }) => { + const termId = generateTermId( + isLink + ? { area1: selectedArea, area2: id } + : { area: selectedArea, cluster: id }, + ); + + // Check if the id is valid + if ( + id === selectedClusterOrArea || + !isTermExist(constraintTerms, termId) + ) { + acc.push({ name, id: id.toLowerCase() }); } - return ""; - }, - [options, options1], - ); + + return acc; + }, []); + }, [ + selectedArea, + isLink, + list.links, + list.clusters, + selectedClusterOrArea, + constraintTerms, + ]); //////////////////////////////////////////////////////////////// // Event Handlers //////////////////////////////////////////////////////////////// - const handleValue1 = useCallback( - (value: string) => { - const v2 = getFirstValue2(value); - saveValue({ - id: constraint.id, - data: isLink - ? { - area1: value, - area2: v2, - } - : { - area: value, - cluster: v2, - }, - }); - setValue1(value); - setValue2(v2); - }, - [constraint.id, getFirstValue2, isLink, saveValue, setValue1, setValue2], - ); + const handleAreaChange = (value: string) => { + setSelectedArea(value); + }; - const handleValue2 = useCallback( - (value: string) => { - setValue2(value); - saveValue({ - id: constraint.id, - data: isLink - ? { - area1: value1, - area2: value, - } - : { - area: value1, - cluster: value, - }, - }); - }, - [constraint.id, isLink, saveValue, setValue2, value1], - ); + const handleClusterOrAreaChange = (value: string) => { + setSelectedClusterOrArea(value); + saveValue({ + ...term, + data: isLink + ? { area1: selectedArea, area2: value } + : { area: selectedArea, cluster: value }, + }); + }; //////////////////////////////////////////////////////////////// // JSX //////////////////////////////////////////////////////////////// + return ( <> handleValue1(value as string)} + disabled + size="small" + variant="outlined" + name="selectedArea" + label={t(`study.${isLink ? "area1" : "area"}`)} + data={selectedArea} + list={areaOptions} + handleChange={(key, value) => handleAreaChange(value as string)} sx={{ - flexGrow: 1, - minWidth: "200px", - height: "60px", + width: 200, + mr: 1, }} /> handleValue2(value as string)} + size="small" + variant="outlined" + name="selectedClusterOrArea" + label={t(`study.${isLink ? "area2" : "cluster"}`)} + data={selectedClusterOrArea.toLowerCase()} + list={clusterOrAreaOptions} + handleChange={(key, value) => + handleClusterOrAreaChange(value as string) + } sx={{ - flexGrow: 1, - minWidth: "200px", - height: "60px", - ml: 1, + width: 200, }} /> diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintTerm/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintTerm/index.tsx index 136f0f287d..6a4e0fabb0 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintTerm/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintTerm/index.tsx @@ -1,147 +1,223 @@ -import { useCallback, useMemo, useState } from "react"; +import { ChangeEvent, useMemo, useState } from "react"; import { Box, Button, TextField, Typography } from "@mui/material"; import AddCircleOutlineRoundedIcon from "@mui/icons-material/AddCircleOutlineRounded"; import DeleteRoundedIcon from "@mui/icons-material/DeleteRounded"; import { useTranslation } from "react-i18next"; -import { ConstraintType, isDataLink } from "../utils"; -import { - AllClustersAndLinks, - ClusterElement, - LinkCreationInfoDTO, -} from "../../../../../../../../common/types"; +import { ConstraintTerm, isLinkTerm } from "../utils"; +import { AllClustersAndLinks } from "../../../../../../../../common/types"; import OptionsList from "./OptionsList"; -import { ConstraintItemRoot } from "./style"; import ConstraintElement from "../constraintviews/ConstraintElement"; import OffsetInput from "../constraintviews/OffsetInput"; -export type ConstraintWithNullableOffset = Partial< - Omit & { offset: number | null | undefined } ->; - interface Props { options: AllClustersAndLinks; - constraint: ConstraintType; - constraintsTerm: ConstraintType[]; - saveValue: (constraint: ConstraintWithNullableOffset) => void; + term: ConstraintTerm; + constraintTerms: ConstraintTerm[]; + saveValue: (term: ConstraintTerm) => void; deleteTerm: () => void; } -export default function ConstraintItem(props: Props) { - const { options, constraint, constraintsTerm, saveValue, deleteTerm } = props; +/** + * Represents a single constraint term item within the UI, allowing users to + * modify weight, offset, and select areas or clusters based on the term type. + * + * Additionally, the refactor will address the need to incorporate uncontrolled components + * with `react-hook-form` for better form management practices. + * + * @deprecated This component is deprecated due to an upcoming redesign aimed at improving modularity and maintainability. + * It remains functional for current implementations but will be replaced by a more + * modular design. Future versions will introduce separate components for handling cluster terms and link terms more efficiently. + * + * Additionally, the refactor will address the need to incorporate uncontrolled components + * with `react-hook-form` for better form management practices. + * + * @param props - The props @see {Props} + * @param props.options - The available options for areas and clusters. + * @param props.term - The current term being edited, containing its data. + * @param props.constraintTerms - All current terms for validation and to prevent duplicates. + * @param props.saveValue - Callback function to save the updated term to the global state. + * @param props.deleteTerm - Callback function to delete the current term. + * + * @example + * + * + * @returns Constraint Term component of type link or cluster + */ +function ConstraintTermItem({ + options, + term, + constraintTerms, + saveValue, + deleteTerm, +}: Props) { const [t] = useTranslation(); - const [weight, setWeight] = useState(constraint.weight); - const [offset, setOffset] = useState(constraint.offset); - const isLink = useMemo(() => isDataLink(constraint.data), [constraint.data]); - const initValue1 = isLink - ? (constraint.data as LinkCreationInfoDTO).area1 - : (constraint.data as ClusterElement).area; - const initValue2 = isLink - ? (constraint.data as LinkCreationInfoDTO).area2 - : (constraint.data as ClusterElement).cluster; - const [value1, setValue1] = useState(initValue1); - const [value2, setValue2] = useState(initValue2); + const [weight, setWeight] = useState(term.weight); + const [offset, setOffset] = useState(term.offset); + + /** + * Determines the type of constraint term (link or cluster) and initializes + * the relevant states for the area and cluster or the two areas in case of a link. + * + * The component supports two types of terms: + * - LinkTerm: Represents a link between two areas (`area1` and `area2`). + * - ClusterTerm: Represents a cluster within an area (`area` and `cluster`). + * + * The `useMemo` hook is utilized to compute and remember the values based on `term.data`. + * This memoization helps in avoiding unnecessary recalculations during re-renders. + * + * @returns An array where: + * - The first element (`area`) represents the primary area for both link and cluster terms. + * - The second element (`areaOrCluster`) represents either the second area for link terms + * or the cluster for cluster terms. + */ + const [area, areaOrCluster] = useMemo(() => { + // Using isLinkTerm to check if the term's data matches the structure of a LinkTerm + // and accordingly returning the appropriate areas or area and cluster. + return isLinkTerm(term.data) + ? [term.data.area1, term.data.area2] // For LinkTerm: Extracting both areas. + : [term.data.area, term.data.cluster]; // For ClusterTerm: Extracting area and cluster. + }, [term.data]); + + /** + * State hooks for managing the selected area and cluster (or second area for links), + * enabling user interaction and updates to these fields. + * + * - `selectedArea`: State for managing the primary area selection. + * - `selectedClusterOrArea2`: State for managing the secondary selection, + * which could be a cluster (for ClusterTerm) or a second area (for LinkTerm). + */ + const [selectedArea, setSelectedArea] = useState(area); + + const [selectedClusterOrArea, setSelectedClusterOrArea] = + useState(areaOrCluster); //////////////////////////////////////////////////////////////// // Event Handlers //////////////////////////////////////////////////////////////// - const handleChange = useCallback( - (name: "weight" | "offset", value: string | number | null) => { - let pValue = 0; - if (value !== null) { - try { - pValue = typeof value === "number" ? value : parseFloat(value); - pValue = Number.isNaN(pValue) ? 0 : pValue; - } catch (e) { - pValue = 0; - } - } - if (name === "weight") { - setWeight(pValue); - } else { - setOffset(pValue); - } - saveValue({ - id: constraint.id, - [name]: value === null ? value : pValue, - }); - }, - [constraint.id, saveValue], - ); + const handleWeightChange = ( + event: ChangeEvent, + ) => { + const newWeight = parseFloat(event.target.value) || 0; + setWeight(newWeight); + saveValue({ ...term, weight: newWeight }); + }; + + const handleOffsetChange = ( + event: ChangeEvent, + ) => { + const value = event.target.value; + const newOffset = value === "" ? undefined : parseInt(value, 10); + setOffset(newOffset); + saveValue({ ...term, offset: newOffset }); + }; + + const handleOffsetRemove = () => { + if (offset !== undefined && offset > 0) { + saveValue({ ...term, offset: undefined }); + } + setOffset(undefined); + }; + + const handleOffsetAdd = () => { + setOffset(0); + }; //////////////////////////////////////////////////////////////// // JSX - /// ///////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////// return ( - + handleChange("weight", e.target.value)} + onChange={handleWeightChange} + sx={{ maxWidth: 150, mr: 0 }} /> } right={ } /> - {offset !== undefined && offset !== null ? ( - <> - x - t} - right={ - handleChange("offset", null)}> - handleChange("offset", e.target.value)} - /> - - } - /> - - ) : ( + + + {offset !== undefined && offset !== null ? ( + <> + x + t} + right={ + + + + } + /> + + ) : ( + + )} + + + - )} - - + + ); } + +export default ConstraintTermItem; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintTerm/style.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintTerm/style.ts deleted file mode 100644 index d5f6016bf3..0000000000 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintTerm/style.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Box, styled } from "@mui/material"; - -export const ConstraintItemRoot = styled(Box)(({ theme }) => ({ - display: "flex", - width: "100%", - padding: 0, - alignItems: "center", -})); diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/Matrix.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/Matrix.tsx new file mode 100644 index 0000000000..fbd3fb96f8 --- /dev/null +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/Matrix.tsx @@ -0,0 +1,107 @@ +import { useTranslation } from "react-i18next"; +import { MatrixStats, StudyMetadata } from "../../../../../../../common/types"; +import MatrixInput from "../../../../../../common/MatrixInput"; +import { Operator } from "./utils"; +import SplitView from "../../../../../../common/SplitView"; +import { Box, Button } from "@mui/material"; +import BasicDialog, { + BasicDialogProps, +} from "../../../../../../common/dialogs/BasicDialog"; + +interface Props { + study: StudyMetadata; + operator: Operator; + constraintId: string; + open: boolean; + onClose: () => void; +} + +// TODO rename MatrixDialog or ConstraintMatrixDialog +function Matrix({ study, operator, constraintId, open, onClose }: Props) { + const { t } = useTranslation(); + const dialogProps: BasicDialogProps = { + open, + onClose, + actions: ( + + ), + }; + + //////////////////////////////////////////////////////////////// + // JSX + //////////////////////////////////////////////////////////////// + + return ( + + {Number(study.version) >= 870 ? ( + <> + {operator === "less" && ( + + )} + {operator === "equal" && ( + + )} + {operator === "greater" && ( + + )} + {operator === "both" && ( + + + + + + + + + )} + + ) : ( + ", "="]} + computStats={MatrixStats.NOCOL} + /> + )} + + ); +} + +export default Matrix; diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/constraintviews/ConstraintElement.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/constraintviews/ConstraintElement.tsx index c675363650..02b104c14f 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/constraintviews/ConstraintElement.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/constraintviews/ConstraintElement.tsx @@ -1,13 +1,9 @@ import { FormControlLabel, Switch, Typography } from "@mui/material"; import { ReactNode } from "react"; -import { - ConstraintElementData, - ConstraintElementHeader, - ConstraintElementRoot, -} from "./style"; +import { ConstraintElementData, ConstraintElementRoot } from "./style"; +import { useTranslation } from "react-i18next"; interface ElementProps { - title: string; left: ReactNode; right: ReactNode; operator?: string; @@ -15,29 +11,26 @@ interface ElementProps { onToggleType?: () => void; } -export default function ConstraintElement(props: ElementProps) { - const { title, isLink, left, right, operator, onToggleType } = props; +export default function ConstraintElement({ + isLink, + left, + right, + operator, + onToggleType, +}: ElementProps) { + const { t } = useTranslation(); + return ( - - - {title} - + {onToggleType !== undefined && ( } onChange={(event, checked) => onToggleType()} - label={isLink ? "Link" : "Cluster"} - labelPlacement="end" + label={isLink ? t("study.link") : t("study.cluster")} + labelPlacement="bottom" /> )} - - {left} {operator} {right} diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/constraintviews/OffsetInput.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/constraintviews/OffsetInput.tsx index fee733c5c0..c2e7715f7b 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/constraintviews/OffsetInput.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/constraintviews/OffsetInput.tsx @@ -20,8 +20,8 @@ export default function OffsetInput(props: PropsWithChildren) { ({ display: "flex", flexDirection: "column", - padding: theme.spacing(1), - backgroundColor: PAPER_BACKGROUND_NO_TRANSPARENCY, -})); - -export const ConstraintElementHeader = styled(Box)(({ theme }) => ({ - width: "100%", - display: "flex", - justifyContent: "space-between", - alignItems: "center", + padding: theme.spacing(0.8), + borderRadius: 5, + backgroundImage: + "linear-gradient(rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.05))", })); export const ConstraintElementData = styled(Box)(({ theme }) => ({ diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/index.tsx index afaef4287b..85dc4c0993 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/index.tsx @@ -1,55 +1,175 @@ -import { Box, Paper } from "@mui/material"; -import { useOutletContext } from "react-router"; -import { StudyMetadata } from "../../../../../../../common/types"; -import usePromise from "../../../../../../../hooks/usePromise"; +import { ACTIVE_WINDOWS_DOC_PATH, BindingConstraint } from "./utils"; +import { Box, Button, Paper } from "@mui/material"; import Form from "../../../../../../common/Form"; -import BindingConstForm from "./BindingConstForm"; -import { getDefaultValues } from "./utils"; import UsePromiseCond, { mergeResponses, } from "../../../../../../common/utils/UsePromiseCond"; -import useStudySynthesis from "../../../../../../../redux/hooks/useStudySynthesis"; +import { + getBindingConstraint, + updateBindingConstraint, +} from "../../../../../../../services/api/studydata"; +import { useOutletContext } from "react-router"; + +import { AxiosError } from "axios"; +import BindingConstForm from "./BindingConstForm"; +import { CommandEnum } from "../../../../Commands/Edition/commandTypes"; +import ConfirmationDialog from "../../../../../../common/dialogs/ConfirmationDialog"; +import ConstraintFields from "./ConstraintFields"; +import Delete from "@mui/icons-material/Delete"; +import DocLink from "../../../../../../common/DocLink"; +import { StudyMetadata } from "../../../../../../../common/types"; +import { SubmitHandlerPlus } from "../../../../../../common/Form/types"; +import { appendCommands } from "../../../../../../../services/api/variant"; import { getLinksAndClusters } from "../../../../../../../redux/selectors"; +import { setCurrentBindingConst } from "../../../../../../../redux/ducks/studySyntheses"; +import { t } from "i18next"; +import useAppDispatch from "../../../../../../../redux/hooks/useAppDispatch"; +import useEnqueueErrorSnackbar from "../../../../../../../hooks/useEnqueueErrorSnackbar"; +import usePromise from "../../../../../../../hooks/usePromise"; +import { useSnackbar } from "notistack"; +import { useState } from "react"; +import useStudySynthesis from "../../../../../../../redux/hooks/useStudySynthesis"; interface Props { - bindingConst: string; + constraintId: string; } -function BindingConstView(props: Props) { +// TODO rename Form (its the constraint form => properties form + terms form) +function BindingConstView({ constraintId }: Props) { const { study } = useOutletContext<{ study: StudyMetadata }>(); - const { bindingConst } = props; - const defaultValuesRes = usePromise( - () => getDefaultValues(study.id, bindingConst), - [study.id, bindingConst], + const dispatch = useAppDispatch(); + const { enqueueSnackbar } = useSnackbar(); + const enqueueErrorSnackbar = useEnqueueErrorSnackbar(); + const [deleteConstraintDialogOpen, setDeleteConstraintDialogOpen] = + useState(false); + + const constraint = usePromise( + () => getBindingConstraint(study.id, constraintId), + [study.id, constraintId], ); - const optionsRes = useStudySynthesis({ + + const linksAndClusters = useStudySynthesis({ studyId: study.id, selector: (state) => getLinksAndClusters(state, study.id), }); + //////////////////////////////////////////////////////////////// + // Event handlers + //////////////////////////////////////////////////////////////// + + const handleSubmitConstraint = ({ + values, + }: SubmitHandlerPlus) => { + const { id, name, ...updatedConstraint } = values; + + return updateBindingConstraint(study.id, constraintId, updatedConstraint); + }; + + /** + * @deprecated + * We should use a dedicated DELETE endpoint for removing binding constraints. This endpoint is + * not currently exposed by the API, but it is recommended to transition to it once available. + * + * This function sends a commandto remove the binding constraint by its ID. + * After successful deletion, it triggers a UI update to reflect the removal. + */ + const handleDeleteConstraint = async () => { + try { + await appendCommands(study.id, [ + { + action: CommandEnum.REMOVE_BINDING_CONSTRAINT, + args: { + id: constraintId, + }, + }, + ]); + + // Trigger a reload redirecting to the first constraint + dispatch(setCurrentBindingConst("")); + + enqueueSnackbar(t("study.success.deleteConstraint"), { + variant: "success", + }); + } catch (e) { + enqueueErrorSnackbar(t("study.error.deleteConstraint"), e as AxiosError); + } finally { + setDeleteConstraintDialogOpen(false); + } + }; + //////////////////////////////////////////////////////////////// // JSX //////////////////////////////////////////////////////////////// return ( - - - ( -
- {bindingConst && ( + + ( + <> + + + + + {/* Constraint properties form */} + + + + + + {/* Constraint terms form */} + +
- )} - + +
+ + )} + /> + + {deleteConstraintDialogOpen && ( + setDeleteConstraintDialogOpen(false)} + onConfirm={handleDeleteConstraint} + alert="warning" + open + > + {t( + "study.modelization.bindingConst.question.deleteBindingConstraint", )} - /> -
-
+ + )} + ); } diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/style.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/style.ts deleted file mode 100644 index 6d2b44dfb0..0000000000 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/style.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Box, Tabs, styled } from "@mui/material"; - -export const ConstraintList = styled(Box)(({ theme }) => ({ - display: "flex", - width: "100%", - flexDirection: "column", - marginBottom: theme.spacing(1), -})); - -export const ConstraintHeader = styled(Box)(({ theme }) => ({ - width: "100%", - display: "flex", - justifyContent: "flex-end", - alignItems: "center", - marginBottom: theme.spacing(2), -})); - -export const ConstraintTerm = styled(Box)(({ theme }) => ({ - display: "flex", - width: "100%", - flexDirection: "column", -})); - -export const MatrixContainer = styled(Box)(({ theme }) => ({ - display: "flex", - flexDirection: "column", - width: "100%", - height: "500px", - paddingRight: theme.spacing(2), - marginBottom: theme.spacing(6), -})); - -export const StyledTab = styled(Tabs)({ - width: "100%", - borderBottom: 1, - borderColor: "divider", -}); diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/utils.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/utils.ts index 65af894d24..2c6bcdb00d 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/utils.ts @@ -1,114 +1,214 @@ -import { - ClusterElement, - LinkClusterItem, - LinkCreationInfoDTO, -} from "../../../../../../../common/types"; -import { getBindingConstraint } from "../../../../../../../services/api/studydata"; -import { FilteringType } from "../../../common/types"; +//////////////////////////////////////////////////////////////// +// Constants +//////////////////////////////////////////////////////////////// -type OperatorType = "less" | "equal" | "greater" | "both"; +export const ACTIVE_WINDOWS_DOC_PATH = + "https://antares-simulator.readthedocs.io/en/latest/reference-guide/04-active_windows/"; -export interface ConstraintType { - id: string; - weight: number; - offset?: number; - data: LinkCreationInfoDTO | ClusterElement; +export const OPERATORS = ["less", "equal", "greater", "both"] as const; +export const TIME_STEPS = ["hourly", "daily", "weekly"] as const; +export const OUTPUT_FILTERS = [ + "hourly", + "daily", + "weekly", + "monthly", + "annual", +] as const; + +//////////////////////////////////////////////////////////////// +// Types +//////////////////////////////////////////////////////////////// + +export type Operator = (typeof OPERATORS)[number]; +export type TimeStep = (typeof TIME_STEPS)[number]; +export type OutputFilter = (typeof OUTPUT_FILTERS)[number]; +// ID of a LinkTerm, expecting the "%" separator +export type LinkTermId = `${string}%${string}`; +// ID of a ClusterTerm, expecting the "." separator +export type ClusterTermId = `${string}.${string}`; + +export interface LinkTerm { + id: LinkTermId; + data: { + area1: string; + area2: string; + }; } -export interface UpdateBindingConstraint { - key: string; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - value: any; +export interface ClusterTerm { + id: ClusterTermId; + data: { + area: string; + cluster: string; + }; } -export interface BindingConstFields { - name: string; - id: string; - enabled: boolean; - time_step: Exclude; - operator: OperatorType; - comments?: string; - filterByYear: FilteringType[]; - filterSynthesis: FilteringType[]; - constraints: ConstraintType[]; +export interface ConstraintTerm { + id: LinkTermId | ClusterTermId; + weight: number; + offset?: number; + data: LinkTerm["data"] | ClusterTerm["data"]; } -export interface BindingConstFieldsDTO { - name: string; +export interface BindingConstraint { id: string; + name: string; + group: string; enabled: boolean; - time_step: Exclude; - operator: OperatorType; + timeStep: TimeStep; + operator: Operator; comments?: string; - filter_year_by_year?: string; - filter_synthesis?: string; - constraints: ConstraintType[]; + filterSynthesis: OutputFilter[]; + filterYearByYear: OutputFilter[]; + terms: ConstraintTerm[]; } -export type BindingConstPath = Record; +//////////////////////////////////////////////////////////////// +// Functions +//////////////////////////////////////////////////////////////// -export async function getDefaultValues( - studyId: string, - bindingConstId: string, -): Promise { - // Fetch fields - const fields: BindingConstFieldsDTO = await getBindingConstraint( - studyId, - bindingConstId, - ); - return { - ...fields, - comments: fields.comments || "", - filterByYear: (fields.filter_year_by_year || "").split(",").map((elm) => { - const sElm = elm.replace(/\s+/g, ""); - return sElm as FilteringType; - }), - filterSynthesis: (fields.filter_synthesis || "").split(",").map((elm) => { - const sElm = elm.replace(/\s+/g, ""); - return sElm as FilteringType; - }), - }; -} +/** + * Checks if the given term data represents a link term. + * + * @param termData - The term data to check, which could represent either a link term or a cluster term. + * @returns True if the term data represents a link term, false otherwise. + */ +export function isLinkTerm( + termData: LinkTerm["data"] | ClusterTerm["data"], +): termData is LinkTerm["data"] { + if (!termData) { + return false; + } -export function isDataLink( - data: LinkCreationInfoDTO | ClusterElement, -): data is LinkCreationInfoDTO { - return (data as LinkCreationInfoDTO).area1 !== undefined; + if (!("area1" in termData && "area2" in termData)) { + return false; + } + + return termData.area1 !== "" && termData.area2 !== ""; } -export function dataToId(data: LinkCreationInfoDTO | ClusterElement): string { - if (isDataLink(data)) { - const link = data; - return `${link.area1}%${link.area2}`; +/** + * Generates a unique identifier from the given term. + * The term can be either a link term (2 areas) or a cluster term (area + cluster). + * For a link term, the identifier format is "area1%area2". + * For a cluster term, the identifier format is "area.cluster". + * + * @param termData - The term data from which to generate the identifier. + * @returns The generated unique identifier. + */ +export function generateTermId( + termData: LinkTerm["data"] | ClusterTerm["data"], +): LinkTermId | ClusterTermId { + if (isLinkTerm(termData)) { + return `${termData.area1}%${termData.area2}`; } - const cluster = data; - return `${cluster.area}.${cluster.cluster}`; + return `${termData.area}.${termData.cluster}`; } -export const isOptionExist = ( - list: LinkClusterItem[], - value1: string, - value2: string, -): boolean => { - const index1 = list.findIndex((item) => item.element.id === value1); - if (index1 < 0) { - return false; +/** + * Checks if a term with the specified ID exists in the list of terms. + * + * @param terms - The array of ConstraintTerm objects to search through. + * @param termId - The unique identifier of the term, either a LinkTermId or a ClusterTermId. + * @returns True if a term with the specified ID exists; otherwise, false. + */ +export const isTermExist = ( + terms: ConstraintTerm[], + termId: LinkTermId | ClusterTermId, +): boolean => terms.some(({ id }) => id === termId); + +/** + * !WARNING: Temporary Workaround (Model adapter) + * The following functions serves as a workaround to align the API's data model with the UI's requirements due to the current mismatch + * between the expected data formats. Specifically, it toggles the input format between a string and an array of strings + * (or in this context, OutputFilters) to accommodate the UI's handling of these fields. + * + * This transformation is necessary because the API currently provides these fields in a format not directly usable by the UI, + * necessitating their conversion. It is important to note that this approach may introduce maintenance overhead and potential + * points of failure, as it relies on the specific current structure of the API responses and UI expectations. + * + * Ideally, this transformation should be removed once the API's model is updated to natively support the data formats + * required by the UI, thereby eliminating the need for such manual conversions and ensuring a more robust and direct + * data flow between the API and the UI components. + * + * TODO: Monitor the API model updates and remove this workaround when possible, ensuring direct compatibility. + */ + +/** + * Checks if a given array consists only of valid OutputFilter values. + * + * @param array - The array to be checked. + * @returns True if all items in the array are valid OutputFilter values, false otherwise. + */ +function isValidOutputFilterInput(array: string[]): array is OutputFilter[] { + return array.every((item) => OUTPUT_FILTERS.includes(item as OutputFilter)); +} + +/** + * Converts between a string and an array of OutputFilter values, depending on the input type. + * + * @param data - The data to be converted. + * @returns The converted data. + * @throws If the input is neither a string nor an array of OutputFilter values. + */ +function adaptOutputFilterFormat( + data: string | OutputFilter[] | undefined, +): string | OutputFilter[] { + // Handle case where the fields are undefined in versions below 8.3. + if (data === undefined) { + return []; } - const index2 = list[index1].item_list.findIndex((item) => item.id === value2); - if (index2 < 0) { - return false; + // Handle empty string as an empty array of filters. + if (typeof data === "string") { + if (data.length === 0) { + return []; + } + + // Convert filters string to array. + const filtersArray = data.split(/\s*,\s*/); + + if (isValidOutputFilterInput(filtersArray)) { + return filtersArray; + } else { + throw new Error("String contains invalid output filters values"); + } } - return true; -}; + // Convert filters array to string, handling empty array as an empty string. + if (Array.isArray(data)) { + if (data.length === 0) { + return ""; + } -export const isTermExist = ( - list: ConstraintType[], - termId: string, -): boolean => { - return list.findIndex((item) => item.id === termId) >= 0; -}; + if (isValidOutputFilterInput(data)) { + return data.map((filter) => filter.trim()).join(","); + } else { + throw new Error("Array contains invalid output filters values"); + } + } -export const ACTIVE_WINDOWS_DOC_PATH = - "https://antares-simulator.readthedocs.io/en/latest/reference-guide/04-active_windows/"; + throw new Error( + "Invalid input: Expected a string or an array of OutputFilter values", + ); +} + +/** + * Adapts fields within a BindingConstraint object to match the expected data formats, facilitating + * the alignment of API data with UI requirements. + * + * @param data - The BindingConstraint object to transform. + * @returns The transformed BindingConstraint object. + */ +export function bindingConstraintModelAdapter( + data: BindingConstraint, +): BindingConstraint { + const filterSynthesis = adaptOutputFilterFormat(data.filterSynthesis); + const filterYearByYear = adaptOutputFilterFormat(data.filterYearByYear); + + return { + ...data, + filterSynthesis: filterSynthesis as typeof data.filterSynthesis, + filterYearByYear: filterYearByYear as typeof data.filterYearByYear, + }; +} diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/index.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/index.tsx index 2836f7fce0..b8fd1d1d32 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/index.tsx @@ -1,11 +1,8 @@ import { Box } from "@mui/material"; -import * as R from "ramda"; -import { ReactNode } from "react"; import { useOutletContext } from "react-router"; import { StudyMetadata } from "../../../../../../common/types"; import SimpleLoader from "../../../../../common/loaders/SimpleLoader"; import SimpleContent from "../../../../../common/page/SimpleContent"; -import SplitLayoutView from "../../../../../common/SplitLayoutView"; import BindingConstPropsView from "./BindingConstPropsView"; import { getBindingConst, @@ -18,25 +15,42 @@ import BindingConstView from "./BindingConstView"; import usePromise from "../../../../../../hooks/usePromise"; import { getBindingConstraintList } from "../../../../../../services/api/studydata"; import UsePromiseCond from "../../../../../common/utils/UsePromiseCond"; +import { useEffect } from "react"; +import SplitView from "../../../../../common/SplitView"; function BindingConstraints() { const { study } = useOutletContext<{ study: StudyMetadata }>(); + const dispatch = useAppDispatch(); + + const currentConstraintId = useAppSelector(getCurrentBindingConstId); + const bindingConstraints = useAppSelector((state) => getBindingConst(state, study.id), ); - const res = usePromise( + + // TODO find better name + const constraints = usePromise( () => getBindingConstraintList(study.id), [study.id, bindingConstraints], ); - const currentBindingConst = useAppSelector(getCurrentBindingConstId); - const dispatch = useAppDispatch(); + + useEffect(() => { + const { data } = constraints; + + if (!data || data.length === 0 || currentConstraintId) { + return; + } + + const firstConstraintId = data[0].id; + dispatch(setCurrentBindingConst(firstConstraintId)); + }, [constraints, currentConstraintId, dispatch]); //////////////////////////////////////////////////////////////// // Event Handlers //////////////////////////////////////////////////////////////// - const handleBindingConstClick = (bindingConstId: string): void => { - dispatch(setCurrentBindingConst(bindingConstId)); + const handleConstraintChange = (constraintId: string): void => { + dispatch(setCurrentBindingConst(constraintId)); }; //////////////////////////////////////////////////////////////// @@ -44,43 +58,27 @@ function BindingConstraints() { //////////////////////////////////////////////////////////////// return ( - } - ifResolved={(data) => ( - - - - )} - /> - } - right={ - <> - {R.cond([ - // Binding constraints list - [ - () => !!currentBindingConst && res.data !== undefined, - () => - ( - - ) as ReactNode, - ], - // No Areas - [ - R.T, - () => - () as ReactNode, - ], - ])()} - - } + } + ifResolved={(data) => ( + + + + + + {currentConstraintId && ( + + )} + + + )} + ifRejected={(error) => } /> ); } diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/utils.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/utils.ts index 742ebe152a..1117d461a5 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Map/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Map/utils.ts @@ -83,7 +83,15 @@ export const getTextColor = (bgColor: RGB): string => { //////////////////////////////////////////////////////////////// /** - * Sets the graph nodes from the nodes data + * Custom hook to compute and return nodes with adjusted positions based on the current layer and view settings. + * It adjusts node positions to ensure they are correctly positioned in the graph based on the current zoom level and layer. + * Additionally, it calculates the color for each node, supporting layer-specific color adjustments. + * + * @param nodes - Array of nodes to render. + * @param width - Width of the rendering area. + * @param height - Height of the rendering area. + * @param currentLayerId - The ID of the current layer, used to adjust node positions and colors. + * @returns Array of nodes with updated positions and colors for rendering. */ export function useRenderNodes( nodes: StudyMapNode[], diff --git a/webapp/src/components/App/Singlestudy/explore/Results/ResultDetails/index.tsx b/webapp/src/components/App/Singlestudy/explore/Results/ResultDetails/index.tsx index 763405900a..8f4d0ce2f6 100644 --- a/webapp/src/components/App/Singlestudy/explore/Results/ResultDetails/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Results/ResultDetails/index.tsx @@ -1,6 +1,5 @@ import { Box, - Button, Paper, Skeleton, ToggleButton, @@ -12,7 +11,6 @@ import { useTranslation } from "react-i18next"; import { useNavigate, useOutletContext, useParams } from "react-router"; import axios from "axios"; import GridOffIcon from "@mui/icons-material/GridOff"; -import DownloadOutlinedIcon from "@mui/icons-material/DownloadOutlined"; import { Area, LinkElement, @@ -44,12 +42,12 @@ import UsePromiseCond, { mergeResponses, } from "../../../../../common/utils/UsePromiseCond"; import useStudySynthesis from "../../../../../../redux/hooks/useStudySynthesis"; -import { downloadMatrix } from "../../../../../../utils/matrixUtils"; import ButtonBack from "../../../../../common/ButtonBack"; import BooleanFE from "../../../../../common/fieldEditors/BooleanFE"; import SelectFE from "../../../../../common/fieldEditors/SelectFE"; import NumberFE from "../../../../../common/fieldEditors/NumberFE"; import moment from "moment"; +import DownloadMatrixButton from "../../../../../common/DownloadMatrixButton.tsx"; function ResultDetails() { const { study } = useOutletContext<{ study: StudyMetadata }>(); @@ -62,7 +60,7 @@ function ResultDetails() { const { data: output } = outputRes; const [dataType, setDataType] = useState(DataType.General); - const [timestep, setTimeStep] = useState(Timestep.Hourly); + const [timestep, setTimestep] = useState(Timestep.Hourly); const [year, setYear] = useState(-1); const [itemType, setItemType] = useState(OutputItemType.Areas); const [selectedItemId, setSelectedItemId] = useState(""); @@ -105,17 +103,22 @@ function ResultDetails() { [filteredItems], ); + const path = useMemo(() => { + if (output && selectedItem && !isSynthesis) { + return createPath({ + output, + item: selectedItem, + dataType, + timestep, + year, + }); + } + return ""; + }, [output, selectedItem, isSynthesis, dataType, timestep, year]); + const matrixRes = usePromise( async () => { - if (output && selectedItem && !isSynthesis) { - const path = createPath({ - output, - item: selectedItem, - dataType, - timestep, - year, - }); - + if (path) { const res = await getStudyData(study.id, path); if (typeof res === "string") { const fixed = res @@ -131,18 +134,17 @@ function ResultDetails() { { resetDataOnReload: true, resetErrorOnReload: true, - deps: [study.id, output, selectedItem, dataType, timestep, year], + deps: [study.id, path], }, ); - const { data: synthesis } = usePromise( - async () => { + const { data: synthesis } = usePromise( + () => { if (outputId && selectedItem && isSynthesis) { const path = `output/${outputId}/economy/mc-all/grid/${selectedItem.id}`; - const res = await getStudyData(study.id, path); - return res; + return getStudyData(study.id, path); } - return null; + return Promise.resolve(null); }, { deps: [study.id, outputId, selectedItem], @@ -151,7 +153,9 @@ function ResultDetails() { // !NOTE: Workaround to display the date in the correct format, to be replaced by a proper solution. const dateTimeFromIndex = useMemo(() => { - if (!matrixRes.data) return []; + if (!matrixRes.data) { + return []; + } // Annual format has a static string if (timestep === Timestep.Annual) { @@ -201,10 +205,6 @@ function ResultDetails() { } }; - const handleDownload = (matrixData: MatrixType, fileName: string): void => { - downloadMatrix(matrixData, fileName); - }; - //////////////////////////////////////////////////////////////// // JSX //////////////////////////////////////////////////////////////// @@ -363,7 +363,7 @@ function ResultDetails() { size="small" variant="outlined" onChange={(event) => { - setTimeStep(event?.target.value as Timestep); + setTimestep(event?.target.value as Timestep); }} /> ), @@ -383,19 +383,7 @@ function ResultDetails() { ))} - + + TABLE_MODE_TYPES.map((type) => ({ + value: type, + label: t(`tableMode.type.${type}`), + })), + [t], + ); + //////////////////////////////////////////////////////////////// // JSX //////////////////////////////////////////////////////////////// @@ -43,7 +52,7 @@ function TableTemplateFormDialog(props: TableTemplateFormDialogProps) { onSubmit={onSubmit} onCancel={onCancel} > - {({ control, resetField, getValues }) => ( + {({ control, setValue, getValues }) => ( resetField("columns")} + onChange={() => setValue("columns", [])} name="type" control={control} /> { //////////////////////////////////////////////////////////////// /** - * Allows to check columns validity for specified type. + * Allows to check columns validity for specified type. Creates a table template with unique ID, name, type, and columns configuration. + * This function is intended to define the structure and type of data that a table can hold. + * + * @param name - The name of the table template. + * @param type - The type of the table, determining the allowed columns and their configuration based on the table mode type. + * @param columns - The configuration of columns specific to the table mode type. + * @returns A table template object including a unique ID, name, type, and columns configuration. */ export function createTableTemplate( name: string, diff --git a/webapp/src/components/App/Singlestudy/explore/Xpansion/Candidates/CreateCandidateDialog.tsx b/webapp/src/components/App/Singlestudy/explore/Xpansion/Candidates/CreateCandidateDialog.tsx index 0ff68a7ed0..eca88218e4 100644 --- a/webapp/src/components/App/Singlestudy/explore/Xpansion/Candidates/CreateCandidateDialog.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Xpansion/Candidates/CreateCandidateDialog.tsx @@ -24,7 +24,7 @@ interface PropType { function CreateCandidateDialog(props: PropType) { const { open, links, onClose, onSave, candidates } = props; const [t] = useTranslation(); - const [isToggled, setToggle] = useState(true); + const [isToggled, setIsToggled] = useState(true); const existingCandidates = useMemo( () => candidates.map(({ name }) => name), @@ -36,7 +36,7 @@ function CreateCandidateDialog(props: PropType) { //////////////////////////////////////////////////////////////// const handleToggle = () => { - setToggle(!isToggled); + setIsToggled(!isToggled); }; const handleSubmit = (data: SubmitHandlerPlus) => { diff --git a/webapp/src/components/App/Singlestudy/explore/common/OutputFilters.tsx b/webapp/src/components/App/Singlestudy/explore/common/OutputFilters.tsx index 3f8875107d..046ada24c3 100644 --- a/webapp/src/components/App/Singlestudy/explore/common/OutputFilters.tsx +++ b/webapp/src/components/App/Singlestudy/explore/common/OutputFilters.tsx @@ -35,6 +35,8 @@ function OutputFilters(props: Props) { multiple options={filterOptions} label={t(`study.outputFilters.${filterName}`)} + size="small" + variant="outlined" control={control} rules={{ onAutoSubmit: (value) => { @@ -44,11 +46,12 @@ function OutputFilters(props: Props) { onAutoSubmit(filterName, selection.join(", ")); }, }} + sx={{ maxWidth: 220 }} /> ); return ( -
+
{renderFilter("filterSynthesis")} {renderFilter("filterByYear")}
diff --git a/webapp/src/components/App/Studies/ExportModal/ExportFilter/index.tsx b/webapp/src/components/App/Studies/ExportModal/ExportFilter/index.tsx index e751898f5a..e7a7fc9e85 100644 --- a/webapp/src/components/App/Studies/ExportModal/ExportFilter/index.tsx +++ b/webapp/src/components/App/Studies/ExportModal/ExportFilter/index.tsx @@ -35,7 +35,7 @@ interface PropTypes { function ExportFilterModal(props: PropTypes) { const [t] = useTranslation(); const { output, synthesis, filter, setFilter } = props; - const [year, setCurrentYear] = useState([]); + const [year, setYear] = useState([]); const [byYear, setByYear] = useState<{ isByYear: boolean; nbYear: number }>({ isByYear: false, nbYear: -1, @@ -105,7 +105,7 @@ function ExportFilterModal(props: PropTypes) { }))} data={year.map((elm) => elm.toString())} setValue={(value: string[] | string) => - setCurrentYear((value as string[]).map((elm) => parseInt(elm, 10))) + setYear((value as string[]).map((elm) => parseInt(elm, 10))) } sx={{ width: "100%", mb: 2 }} required diff --git a/webapp/src/components/App/Studies/ExportModal/index.tsx b/webapp/src/components/App/Studies/ExportModal/index.tsx index 83e426358d..0be51dda04 100644 --- a/webapp/src/components/App/Studies/ExportModal/index.tsx +++ b/webapp/src/components/App/Studies/ExportModal/index.tsx @@ -62,7 +62,8 @@ export default function ExportModal(props: BasicDialogProps & Props) { const [optionSelection, setOptionSelection] = useState("exportWith"); const [outputList, setOutputList] = useState(); const [currentOutput, setCurrentOutput] = useState(); - const [synthesis, setStudySynthesis] = useState(); + const [studySynthesis, setStudySynthesis] = + useState(); const [filter, setFilter] = useState({ type: StudyOutputDownloadType.AREAS, level: StudyOutputDownloadLevelDTO.WEEKLY, @@ -206,7 +207,7 @@ export default function ExportModal(props: BasicDialogProps & Props) { ( diff --git a/webapp/src/components/App/Studies/LauncherDialog.tsx b/webapp/src/components/App/Studies/LauncherDialog.tsx index 1419bfe6ac..7e610e2f88 100644 --- a/webapp/src/components/App/Studies/LauncherDialog.tsx +++ b/webapp/src/components/App/Studies/LauncherDialog.tsx @@ -38,8 +38,10 @@ import CheckBoxFE from "../../common/fieldEditors/CheckBoxFE"; import { convertVersions } from "../../../services/utils"; import UsePromiseCond from "../../common/utils/UsePromiseCond"; import SwitchFE from "../../common/fieldEditors/SwitchFE"; +import moment from "moment"; -const LAUNCH_LOAD_DEFAULT = 22; +const DEFAULT_NB_CPU = 22; +const DEFAULT_TIME_LIMIT = 240 * 3600; // 240 hours in seconds interface Props { open: boolean; @@ -53,8 +55,9 @@ function LauncherDialog(props: Props) { const { enqueueSnackbar } = useSnackbar(); const enqueueErrorSnackbar = useEnqueueErrorSnackbar(); const [options, setOptions] = useState({ - nb_cpu: LAUNCH_LOAD_DEFAULT, + nb_cpu: DEFAULT_NB_CPU, auto_unzip: true, + time_limit: DEFAULT_TIME_LIMIT, }); const [solverVersion, setSolverVersion] = useState(); const [isLaunching, setIsLaunching] = useState(false); @@ -170,12 +173,16 @@ function LauncherDialog(props: Props) { // Utils //////////////////////////////////////////////////////////////// - const timeLimitParse = (value: string): number => { - try { - return parseInt(value, 10) * 3600; - } catch { - return 48 * 3600; - } + /** + * Parses an hour value from a string and converts it to seconds. + * If the input is invalid, returns a default value. + * + * @param hourString - A string representing the number of hours. + * @returns The equivalent number of seconds, or a default value for invalid inputs. + */ + const parseHoursToSeconds = (hourString: string): number => { + const seconds = moment.duration(hourString, "hours").asSeconds(); + return seconds > 0 ? seconds : DEFAULT_TIME_LIMIT; }; //////////////////////////////////////////////////////////////// @@ -265,9 +272,10 @@ function LauncherDialog(props: Props) { label={t("study.timeLimit")} type="number" variant="filled" - value={(options.time_limit ?? 864000) / 3600} // 240 hours default + // Convert from seconds to hours the displayed value + value={(options.time_limit ?? DEFAULT_TIME_LIMIT) / 3600} onChange={(e) => - handleChange("time_limit", timeLimitParse(e.target.value)) + handleChange("time_limit", parseHoursToSeconds(e.target.value)) } InputLabelProps={{ shrink: true, diff --git a/webapp/src/components/App/index.tsx b/webapp/src/components/App/index.tsx index be247e296b..9a3d442c18 100644 --- a/webapp/src/components/App/index.tsx +++ b/webapp/src/components/App/index.tsx @@ -5,8 +5,8 @@ import { Routes, Outlet, } from "react-router-dom"; -import { CssBaseline, ThemeProvider } from "@mui/material"; -import { SnackbarProvider } from "notistack"; +import { CssBaseline, IconButton, ThemeProvider } from "@mui/material"; +import { SnackbarKey, SnackbarProvider, useSnackbar } from "notistack"; import maintheme from "../../theme"; import MenuWrapper from "../wrappers/MenuWrapper"; import Studies from "./Studies"; @@ -54,12 +54,28 @@ import StorageForm from "./Singlestudy/explore/Modelization/Areas/Storages/Form" import ThermalForm from "./Singlestudy/explore/Modelization/Areas/Thermal/Form"; import RenewablesForm from "./Singlestudy/explore/Modelization/Areas/Renewables/Form"; import SplitHydroMatrix from "./Singlestudy/explore/Modelization/Areas/Hydro/SplitHydroMatrix"; +import CloseIcon from "@mui/icons-material/Close"; + +// TODO: replace 'notistack' by 'sonner' (https://sonner.emilkowal.ski/) +function SnackbarCloseButton({ snackbarKey }: { snackbarKey: SnackbarKey }) { + const { closeSnackbar } = useSnackbar(); + + return ( + closeSnackbar(snackbarKey)}> + + + ); +} function App() { return ( - + } + > diff --git a/webapp/src/components/common/DownloadMatrixButton.tsx b/webapp/src/components/common/DownloadMatrixButton.tsx new file mode 100644 index 0000000000..49551eb0f7 --- /dev/null +++ b/webapp/src/components/common/DownloadMatrixButton.tsx @@ -0,0 +1,85 @@ +import FileUploadIcon from "@mui/icons-material/FileUpload"; +import SplitButton from "./buttons/SplitButton.tsx"; +import { downloadMatrix } from "../../services/api/studies/raw/index.ts"; +import { downloadFile } from "../../utils/fileUtils.ts"; +import { useState } from "react"; +import { StudyMetadata } from "../../common/types.ts"; +import useEnqueueErrorSnackbar from "../../hooks/useEnqueueErrorSnackbar.tsx"; +import { useTranslation } from "react-i18next"; + +export interface DownloadMatrixButtonProps { + studyId: StudyMetadata["id"]; + path?: string; + disabled?: boolean; + label?: string; +} + +const EXPORT_OPTIONS = [ + { label: "TSV", value: "tsv" }, + { label: "Excel", value: "xlsx" }, +] as const; + +type ExportFormat = (typeof EXPORT_OPTIONS)[number]["value"]; + +function DownloadMatrixButton(props: DownloadMatrixButtonProps) { + const { t } = useTranslation(); + const { studyId, path, disabled, label = t("global.export") } = props; + const [isDownloading, setIsDownloading] = useState(false); + const enqueueErrorSnackbar = useEnqueueErrorSnackbar(); + + //////////////////////////////////////////////////////////////// + // Event Handlers + //////////////////////////////////////////////////////////////// + + const handleDownload = async (format: ExportFormat) => { + if (!path) { + return; + } + + setIsDownloading(true); + + const isExcel = format === "xlsx"; + + try { + const res = await downloadMatrix({ + studyId, + path, + format, + header: isExcel, + index: isExcel, + }); + + downloadFile( + res, + `matrix_${studyId}_${path.replace("/", "_")}.${format}`, + ); + } catch (err) { + enqueueErrorSnackbar(t("global.download.error"), String(err)); + } + + setIsDownloading(false); + }; + + //////////////////////////////////////////////////////////////// + // JSX + //////////////////////////////////////////////////////////////// + + return ( + , + loadingPosition: "start", + loading: isDownloading, + }} + > + {label} + + ); +} + +export default DownloadMatrixButton; diff --git a/webapp/src/components/common/FormGenerator/AutoSubmitGenerator.tsx b/webapp/src/components/common/FormGenerator/AutoSubmitGenerator.tsx deleted file mode 100644 index 7082a9c23c..0000000000 --- a/webapp/src/components/common/FormGenerator/AutoSubmitGenerator.tsx +++ /dev/null @@ -1,48 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import * as R from "ramda"; -import { useMemo } from "react"; -import { FieldValues } from "react-hook-form"; -import FormGenerator, { - IFieldsetType, - IFormGenerator, - IGeneratorField, -} from "."; - -interface AutoSubmitGeneratorFormProps { - jsonTemplate: IFormGenerator; - saveField: ( - name: IGeneratorField["name"], - path: string, - defaultValues: any, - data: any, - ) => void; -} -export default function AutoSubmitGeneratorForm( - props: AutoSubmitGeneratorFormProps, -) { - const { saveField, jsonTemplate } = props; - - const formattedJsonTemplate: IFormGenerator = useMemo( - () => - jsonTemplate.map((fieldset) => { - const { fields, ...otherProps } = fieldset; - // TODO Remove this component with the update of binding constraints form!! - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - const formattedFields: IFieldsetType["fields"] = fields.map( - (field) => ({ - ...field, - rules: (name, path, required, defaultValues) => ({ - onAutoSubmit: R.curry(saveField)(name, path, defaultValues), - required, - }), - }), - ); - - return { fields: formattedFields, ...otherProps }; - }), - [jsonTemplate, saveField], - ); - - return ; -} diff --git a/webapp/src/components/common/FormGenerator/index.tsx b/webapp/src/components/common/FormGenerator/index.tsx deleted file mode 100644 index b91dc7c9bc..0000000000 --- a/webapp/src/components/common/FormGenerator/index.tsx +++ /dev/null @@ -1,173 +0,0 @@ -import * as R from "ramda"; -import * as RA from "ramda-adjunct"; -import { v4 as uuidv4 } from "uuid"; -import { FieldValues, FormState, Path } from "react-hook-form"; -import { useTranslation } from "react-i18next"; -import { SxProps, Theme } from "@mui/material"; -import { Fragment, ReactNode, useMemo } from "react"; -import SelectFE, { SelectFEProps } from "../fieldEditors/SelectFE"; -import StringFE from "../fieldEditors/StringFE"; -import Fieldset from "../Fieldset"; -import { useFormContextPlus } from "../Form"; -import NumberFE from "../fieldEditors/NumberFE"; -import SwitchFE from "../fieldEditors/SwitchFE"; -import BooleanFE, { BooleanFEProps } from "../fieldEditors/BooleanFE"; -import { RegisterOptionsPlus } from "../Form/types"; - -export type GeneratorFieldType = - | "text" - | "number" - | "select" - | "switch" - | "boolean"; - -export interface IGeneratorField { - type: GeneratorFieldType; - name: Path & (string | undefined); - label: string; - path: string; - sx?: SxProps | undefined; - required?: boolean | string; - rules?: ( - name: IGeneratorField["name"], - path: string, - required?: boolean | string, - defaultValues?: FormState["defaultValues"], - ) => - | Omit< - RegisterOptionsPlus & (string | undefined)>, - "disabled" | "valueAsNumber" | "valueAsDate" | "setValueAs" - > - | undefined; -} - -export interface SelectField extends IGeneratorField { - options: SelectFEProps["options"]; -} - -export interface BooleanField - extends IGeneratorField { - falseText: BooleanFEProps["falseText"]; - trueText: BooleanFEProps["trueText"]; -} - -export type IGeneratorFieldType = - | IGeneratorField - | SelectField - | BooleanField; - -export interface IFieldsetType { - legend: string | ReactNode; - fields: Array>; -} - -export type IFormGenerator = Array>; - -export interface FormGeneratorProps { - jsonTemplate: IFormGenerator; -} - -function formateFieldset(fieldset: IFieldsetType) { - const { fields, ...otherProps } = fieldset; - const formattedFields = fields.map((field) => ({ ...field, id: uuidv4() })); - return { ...otherProps, fields: formattedFields, id: uuidv4() }; -} - -export default function FormGenerator( - props: FormGeneratorProps, -) { - const { jsonTemplate } = props; - const formattedTemplate = useMemo( - () => jsonTemplate.map(formateFieldset), - [jsonTemplate], - ); - const [t] = useTranslation(); - const { - control, - formState: { defaultValues }, - } = useFormContextPlus(); - - return ( - <> - {formattedTemplate.map((fieldset) => ( -
- {fieldset.fields.map((field) => { - const { id, path, rules, type, required, ...otherProps } = field; - const vRules = rules - ? rules(field.name, path, required, defaultValues) - : undefined; - return ( - - {R.cond([ - [ - R.equals("text"), - () => ( - - ), - ], - [ - R.equals("number"), - () => ( - - ), - ], - [ - R.equals("switch"), - () => ( - - ), - ], - [ - R.equals("boolean"), - () => ( - - ), - ], - [ - R.equals("select"), - () => ( - , "id" | "rules">) - .options || [] - } - {...otherProps} - variant="filled" - control={control} - rules={vRules} - /> - ), - ], - ])(type)} - - ); - })} -
- ))} - - ); -} diff --git a/webapp/src/components/common/GroupedDataTable/utils.ts b/webapp/src/components/common/GroupedDataTable/utils.ts index 82673c3877..f209d83bae 100644 --- a/webapp/src/components/common/GroupedDataTable/utils.ts +++ b/webapp/src/components/common/GroupedDataTable/utils.ts @@ -11,9 +11,9 @@ import type { TRow } from "./types"; * If the base value is found in the list of existing values, it appends a number * in the format `(n)` to the base value, incrementing `n` until a unique value is found. * - * @param {string} baseValue - The original base value to check. - * @param {string[]} existingValues - The list of existing values to check against. - * @returns {string} A unique value. + * @param baseValue - The original base value to check for uniqueness. + * @param existingValues - The list of existing values to check against for duplicates. + * @returns A unique value derived from the base value by appending a number in parentheses, if necessary. */ export const generateNextValue = ( baseValue: string, @@ -45,9 +45,9 @@ export const generateNextValue = ( * based on the given original value and the existing values in tableData. * * If the property is "name", the function appends " - copy" to the original value. - * If the property is "id", the function uses nameToId to get the base value. + * If the property is "id", the function uses `nameToId` to get the base value. * - * This function leverages generateNextValue to ensure the uniqueness of the value. + * This function leverages `generateNextValue` to ensure the uniqueness of the value. * * @param originalValue - The original value of the specified property. * @param tableData - The existing table data to check against for ensuring uniqueness. diff --git a/webapp/src/components/common/LogModal.tsx b/webapp/src/components/common/LogModal.tsx index 8dbcdeccb3..74032b95be 100644 --- a/webapp/src/components/common/LogModal.tsx +++ b/webapp/src/components/common/LogModal.tsx @@ -35,7 +35,7 @@ function LogModal(props: Props) { const [logDetail, setLogDetail] = useState(content); const divRef = useRef(null); const logRef = useRef(null); - const [autoscroll, setAutoScroll] = useState(true); + const [autoScroll, setAutoScroll] = useState(true); const [t] = useTranslation(); const updateLog = useCallback( @@ -92,11 +92,11 @@ function LogModal(props: Props) { useEffect(() => { if (logRef.current) { - if (autoscroll) { + if (autoScroll) { scrollToEnd(); } } - }, [logDetail, autoscroll]); + }, [logDetail, autoScroll]); useEffect(() => { if (followLogs) { diff --git a/webapp/src/components/common/MatrixInput/index.tsx b/webapp/src/components/common/MatrixInput/index.tsx index 1bc3d00f33..f2250bd3bc 100644 --- a/webapp/src/components/common/MatrixInput/index.tsx +++ b/webapp/src/components/common/MatrixInput/index.tsx @@ -3,14 +3,11 @@ import { useSnackbar } from "notistack"; import { useState } from "react"; import { AxiosError } from "axios"; import debug from "debug"; -import { Typography, Box, Button, Divider, Tooltip } from "@mui/material"; -import UploadOutlinedIcon from "@mui/icons-material/UploadOutlined"; -import DownloadOutlinedIcon from "@mui/icons-material/DownloadOutlined"; -import InventoryIcon from "@mui/icons-material/Inventory"; +import { Typography, Box, Divider } from "@mui/material"; +import FileDownloadIcon from "@mui/icons-material/FileDownload"; import { MatrixEditDTO, MatrixStats, - MatrixType, StudyMetadata, } from "../../../common/types"; import useEnqueueErrorSnackbar from "../../../hooks/useEnqueueErrorSnackbar"; @@ -23,9 +20,9 @@ import SimpleContent from "../page/SimpleContent"; import EditableMatrix from "../EditableMatrix"; import ImportDialog from "../dialogs/ImportDialog"; import MatrixAssignDialog from "./MatrixAssignDialog"; -import { downloadMatrix } from "../../../utils/matrixUtils"; import { fetchMatrixFn } from "../../App/Singlestudy/explore/Modelization/Areas/Hydro/utils"; -import { LoadingButton } from "@mui/lab"; +import SplitButton from "../buttons/SplitButton"; +import DownloadMatrixButton from "../DownloadMatrixButton.tsx"; const logErr = debug("antares:createimportform:error"); @@ -57,7 +54,6 @@ function MatrixInput({ const [t] = useTranslation(); const [openImportDialog, setOpenImportDialog] = useState(false); const [openMatrixAsignDialog, setOpenMatrixAsignDialog] = useState(false); - const [isDownloading, setIsDownloading] = useState(false); const { data: matrixData, @@ -86,6 +82,7 @@ function MatrixInput({ * Otherwise, default row numbers and timestamps are displayed using initialRowNames. */ const rowNames = fetchFn ? matrixIndex : initialRowNames; + const columnsLength = matrixData?.columns?.length ?? 0; //////////////////////////////////////////////////////////////// // Utils @@ -138,16 +135,6 @@ function MatrixInput({ } }; - const handleDownload = async (matrixData: MatrixType, fileName: string) => { - setIsDownloading(true); - - // Re-fetch to get latest data - const data = await fetchMatrixData(); - downloadMatrix(data, fileName); - - setIsDownloading(false); - }; - //////////////////////////////////////////////////////////////// // JSX //////////////////////////////////////////////////////////////// @@ -166,54 +153,36 @@ function MatrixInput({ > {title || t("xpansion.timeSeries")} - - - - - - {matrixData?.columns?.length >= 1 && ( - } - onClick={() => - handleDownload( - matrixData, - `matrix_${study.id}_${url.replace("/", "_")}`, - ) - } - > - {t("global.download")} - - )} + + {isLoading && } - {!isLoading && matrixData?.columns?.length >= 1 && matrixIndex ? ( + {!isLoading && columnsLength >= 1 && matrixIndex ? ( ) : ( - !isLoading && ( - } - onClick={() => setOpenImportDialog(true)} - > - {t("global.import")} - - } - /> - ) + !isLoading && )} {openImportDialog && ( @@ -250,6 +205,9 @@ function MatrixInput({ dropzoneText={t("matrix.message.importHint")} onClose={() => setOpenImportDialog(false)} onImport={handleImport} + accept={{ + "text/tsv": [".tsv"], + }} /> )} {openMatrixAsignDialog && ( diff --git a/webapp/src/components/common/MatrixInput/style.ts b/webapp/src/components/common/MatrixInput/style.ts index 6fd49fd167..72b77419cb 100644 --- a/webapp/src/components/common/MatrixInput/style.ts +++ b/webapp/src/components/common/MatrixInput/style.ts @@ -13,7 +13,8 @@ export const Root = styled(Box)(({ theme }) => ({ export const Header = styled(Box)(({ theme }) => ({ width: "100%", display: "flex", - flexFlow: "row nowrap", + flexFlow: "row wrap", + gap: theme.spacing(1), justifyContent: "space-between", alignItems: "flex-end", })); diff --git a/webapp/src/components/common/SelectSingle.tsx b/webapp/src/components/common/SelectSingle.tsx index e0a4f212fa..2ada882027 100644 --- a/webapp/src/components/common/SelectSingle.tsx +++ b/webapp/src/components/common/SelectSingle.tsx @@ -4,13 +4,14 @@ import { MenuItem, Select, SelectChangeEvent, + SelectProps, SxProps, Theme, } from "@mui/material"; import { useTranslation } from "react-i18next"; import { GenericInfo } from "../../common/types"; -interface Props { +interface Props extends SelectProps { name: string; label?: string; list: GenericInfo[]; @@ -40,12 +41,9 @@ function SelectSingle(props: Props) { } = props; const [t] = useTranslation(); - const basicHandleChange = (event: SelectChangeEvent) => { - const { - target: { value }, - } = event; + const basicHandleChange = (e: SelectChangeEvent) => { if (setValue) { - setValue(value); + setValue(e.target.value as string); } }; @@ -57,6 +55,7 @@ function SelectSingle(props: Props) { {label}