code: def tutorial(
      ctx: click.core.Context, cfg: CLIContext, msg: bool, clean: bool
  ) -> None:
      """Run user through a tutorial."""
      help_msg = textwrap.dedent(
          """\
          🤓 Please run the following steps,
              1.  Verify that your adapter credentials are correct in `profiles.yml`
              2.  Add time spine model to the models directory (https://docs.getdbt.com/docs/build/metricflow-time-spine)
              3.  Run `dbt seed`, check to see that the steps related to countries, transactions, customers are passing.
              4.  Try validating your data model: `mf validate-configs`
              5.  Check out your metrics: `mf list metrics`
              6.  Check out dimensions for your metric `mf list dimensions --metrics transactions`
              7.  Query your first metric: `mf query --metrics transactions --group-bys metric_time --order metric_time`
              8.  Show the SQL MetricFlow generates:
                  `mf query --metrics transactions --group-bys metric_time --order metric_time --explain`
              9.  Visualize the plan:
                  `mf query --metrics transactions --group-bys metric_time --order metric_time --explain --display-plans`
                  * This only works if you have graphviz installed - see README.
              10.  Add another dimension:
                  `mf query --metrics transactions --group-bys metric_time,customer__customer_country --order metric_time`
              11.  Add a coarser time granularity:
                  `mf query --metrics transactions --group-bys metric_time__week --order metric_time__week`
              12. Try a more complicated query: mf query --metrics transactions,transaction_usd_na --group-bys metric_time,is_large --order metric_time --start-time 2022-03-20 --end-time 2022-04-01.
              13. When you're done with the tutorial, run mf tutorial --clean to delete sample models and seeds.
          """
      )
  
      if msg:
          click.echo(help_msg)
          exit()
  
      if not dbt_project_file_exists():
          click.echo(
              "Unable to detect dbt project. Please ensure that your current working directory is at the root of the dbt project."
          )
          exit()
  
      # TODO: Health checks
  
      # Load the metadata from dbt project
      try:
          dbt_project_metadata = cfg.dbt_project_metadata
          dbt_paths = dbt_project_metadata.dbt_paths
          model_path = (
              pathlib.Path(dbt_paths.model_paths[0]) / "sample_model"
          )
          seed_path = (
              pathlib.Path(dbt_paths.seed_paths[0]) / "sample_seed"
          )
          manifest_path = (
              pathlib.Path(dbt_paths.target_path)
              / "semantic_manifest.json"
          )
      except Exception as e:
          click.echo(
              f"Unable to parse path metadata from dbt project.\nERROR: {str(e)}"
          )
          exit(1)
  
      # Remove sample files from dbt project
      if clean:
          click.confirm(
              "Would you like to remove all the sample files?",
              abort=True,
          )
          spinner = Halo(
              text="Removing sample files...", spinner="dots"
          )
          spinner.start()
          try:
              dbtMetricFlowTutorialHelper.remove_sample_files(
                  model_path=model_path, seed_path=seed_path
              )
              spinner.succeed("🗑️ Sample files has been removed.")
              exit()
          except Exception as e:
              spinner.fail(
                  f"❌ Unable to remove sample files.\nERROR: {str(e)}"
              )
              exit(1)
  
      click.echo(
          textwrap.dedent(
              f"""\
          To begin building and querying metrics, you must define semantic models and
          metric configuration files in your dbt project. dbt will use these files to generate a
          semantic manifest artifact, which MetricFlow will use to create a semantic graph for querying.
          As part of this tutorial, we will generate the following files to help you get started:
  
          📜 model files -> {model_path.absolute().as_posix()}
          🌱 seed files -> {seed_path.absolute().as_posix()}
          ✅ semantic manifest json file -> {manifest_path.absolute().as_posix()}
          """
          )
      )
      click.confirm("Continue and generate the files?", abort=True)
  
      # Generate sample files into dbt project
      if dbtMetricFlowTutorialHelper.check_if_path_exists(
          [model_path, seed_path]
      ):
          click.confirm(
              "There are existing files in the paths above, would you like to overwrite them?",
              abort=True,
          )
          dbtMetricFlowTutorialHelper.remove_sample_files(
              model_path=model_path, seed_path=seed_path
          )
  
      spinner = Halo(text="Generating sample files...", spinner="dots")
      spinner.start()
      dbtMetricFlowTutorialHelper.generate_model_files(
          model_path=model_path,
          profile_schema=dbt_project_metadata.schema,
      )
      dbtMetricFlowTutorialHelper.generate_seed_files(
          seed_path=seed_path
      )
      dbtMetricFlowTutorialHelper.generate_semantic_manifest_file(
          manifest_path=manifest_path
      )
  
      spinner.succeed("📜 Sample files has been generated.")
  
      click.echo(help_msg)
      click.echo(
          "💡 Run `mf tutorial --msg` to see this message again without executing everything else"
      )
      exit()
  
imports: from __future__ import annotations
  import datetime
  import logging
  import pathlib
  import signal
  import sys
  import tempfile
  import textwrap
  import time
  import warnings
  from importlib.metadata import version
  from typing import Callable, List, Optional, Sequence
  import click
  import jinja2
  import pandas
  from dbt_semantic_interfaces.protocols.semantic_manifest import SemanticManifest
  from dbt_semantic_interfaces.validations.semantic_manifest_validator import SemanticManifestValidator
  from dbt_semantic_interfaces.validations.validator_helpers import SemanticManifestValidationResults
  from halo import Halo
  from packaging.version import parse
  from update_checker import UpdateChecker
  import metricflow.cli.custom_click_types
  from metricflow.cli import PACKAGE_NAME
  from metricflow.cli.cli_context import CLIContext
  from metricflow.cli.constants import DEFAULT_RESULT_DECIMAL_PLACES, MAX_LIST_OBJECT_ELEMENTS
  from metricflow.cli.dbt_connectors.dbt_config_accessor import dbtArtifacts
  from metricflow.cli.tutorial import dbtMetricFlowTutorialHelper
  from metricflow.cli.utils import dbt_project_file_exists, error_if_not_in_dbt_project, exception_handler, query_options, start_end_time_options
  from metricflow.dag.dag_visualization import display_dag_as_svg
  from metricflow.dataflow.dataflow_plan_to_text import dataflow_plan_as_text
  from metricflow.engine.metricflow_engine import MetricFlowExplainResult, MetricFlowQueryRequest, MetricFlowQueryResult
  from metricflow.model.data_warehouse_model_validator import DataWarehouseModelValidator
  from metricflow.telemetry.models import TelemetryLevel
  from metricflow.telemetry.reporter import TelemetryReporter, log_call
label_desc: Use image node_id 2 for calling a global function with example usage: tutorial(ctx, cfg, msg, clean) without return types